--- /dev/null
+*) 2004-06-24
+
+ - initial checkin: audio, display, event, input, network
+ (used for my-code/ivac)
+
+################################################################################
--- /dev/null
+/* audio.c -- audio management stuff
+ *
+ * author: hackbard@hackdaworld.dyndns.org
+ *
+ */
+
+#include "audio.h"
+
+int audio_init(t_audio *audio) {
+
+ puts("[audio] initializing audio ...");
+
+ if((audio->dsp_fd=open(audio->dsp_dev,O_RDWR))==-1) {
+ perror("[audio] open call");
+ return A_ERROR;
+ }
+
+ if(ioctl(audio->dsp_fd,SNDCTL_DSP_GETCAPS,&(audio->dsp_cap))==-1) {
+ perror("[audio] ioctl call");
+ return A_ERROR;
+ }
+
+ if(!(audio->dsp_cap&DSP_CAP_DUPLEX)) {
+ puts("[audio] no duplex support");
+ return A_ERROR;
+ }
+
+ return A_SUCCESS;
+}
+
+int audio_setup(t_audio *audio) {
+
+ int tmp;
+
+ puts("[audio] setting up sound device & allocating record/playback buffer");
+
+ tmp=audio->fmt;
+ if(ioctl(audio->dsp_fd,SNDCTL_DSP_SETFMT,&tmp)==-1) {
+ perror("[audio] ioctl call (SNDCTL_DSP_SETFMT)");
+ return A_ERROR;
+ }
+ if(tmp!=audio->fmt) {
+ puts("[audio] FMT not supported");
+ return A_ERROR;
+ }
+
+ tmp=audio->speed;
+ if(ioctl(audio->dsp_fd,SNDCTL_DSP_SPEED,&tmp)==-1) {
+ perror("[audio] ioctl call (SNDCTL_DSP_SPEED)");
+ return A_ERROR;
+ }
+ if(tmp!=audio->speed) {
+ puts("[audio] SPEED not supported");
+ return A_ERROR;
+ }
+
+ if(ioctl(audio->dsp_fd,SNDCTL_DSP_GETBLKSIZE,&(audio->blksize))==-1) {
+ perror("[audio] ioctl call (SNDCTL_DSP_GETBLKSIZE)");
+ return A_ERROR;
+ }
+
+ if((audio->play_data=(unsigned char *)malloc(audio->blksize))==NULL) {
+ perror("[audio] malloc call");
+ return A_ERROR;
+ }
+ if((audio->rec_data=(unsigned char *)malloc(audio->blksize))==NULL) {
+ perror("[audio] malloc call");
+ return A_ERROR;
+ }
+
+ return A_SUCCESS;
+}
+
+int audio_shutdown(t_audio *audio) {
+
+ puts("[audio] shutdown");
+
+ free(audio->play_data);
+ free(audio->rec_data);
+
+ if(close(audio->dsp_fd)==-1) {
+ perror("[audio] close call");
+ return A_ERROR;
+ }
+
+ return A_SUCCESS;
+}
+
+int audio_play(t_audio *audio,int len) {
+
+ int count,left;
+
+ count=0;
+ left=len;
+
+ while(left) {
+ if((count=write(audio->dsp_fd,audio->play_data+len-left,left))==-1) {
+ perror("[audio] write call");
+ return A_ERROR;
+ }
+ left-=count;
+ }
+
+ return A_SUCCESS;
+}
+
+int audio_record(t_audio *audio,int len) {
+
+ int count,left;
+
+ count=0;
+ left=len;
+
+ while(left) {
+ if((count=read(audio->dsp_fd,audio->rec_data+len-left,left))==-1) {
+ perror("[audio] read call");
+ return A_ERROR;
+ }
+ left-=count;
+ }
+
+ return A_SUCCESS;
+}
--- /dev/null
+/* audio.h -- audio headers */
+
+#ifndef AUDIO_H
+#define AUDIO_H
+
+/* includes */
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/ioctl.h>
+#include <sys/soundcard.h>
+
+/* defines */
+#define MAX_CHAR_DEVICE 32
+#define SOUND_DEVICE "/dev/dsp"
+
+#define A_SUCCESS 1
+#define A_ERROR -1
+
+#define BIT_8 AFMT_U8
+#define BIT_16 AFMT_S16_LE
+#define MONO 1
+#define STEREO 2
+
+/* audio specific variables */
+typedef struct s_audio {
+ int dsp_fd;
+ int mixer_fd;
+ char dsp_dev[MAX_CHAR_DEVICE];
+ char mixer_dev[MAX_CHAR_DEVICE];
+ int dsp_cap;
+ int fmt;
+ int channels;
+ int speed;
+ int blksize;
+ int mixer_cap;
+ unsigned char volume;
+ unsigned char *play_data;
+ unsigned char *rec_data;
+} t_audio;
+
+/* function prototypes */
+int audio_init(t_audio *audio);
+int audio_setup(t_audio *audio);
+int audio_shutdown(t_audio *audio);
+int audio_play(t_audio *audio,int len);
+int audio_record(t_audio *audio,int len);
+
+#endif
--- /dev/null
+/* display.c -- display management stuff
+ *
+ * hackbard@hackdaworld.dyndns.org
+ *
+ */
+
+#include "display.h"
+
+// #define USE_NCURSES
+
+int display_init(t_display *display) {
+
+ struct winsize ws;
+
+ /* dimensions */
+ if(ioctl(1,TIOCGWINSZ,&ws)==-1) {
+ perror("[display] ioctl call");
+ return D_ERROR;
+ }
+ display->max_x=ws.ws_col;
+ display->max_y=ws.ws_row;
+
+ printf("[display] initializing display, width: %02d / height: %02d ...\n",
+ ws.ws_col,ws.ws_row);
+
+ /* allocating 'screen' buffer */
+ if((display->screen=(unsigned char *)malloc(display->max_x*display->max_y))
+ ==NULL) {
+ perror("[display] malloc call");
+ return D_ERROR;
+ }
+ /* space as display pixel default */
+ memset(display->screen,0x20,display->max_x*display->max_y);
+
+#ifdef USE_NCURSES
+ initscr();
+ nonl();
+ noecho();
+ cbreak();
+ curs_set(0);
+#endif
+
+ return D_SUCCESS;
+}
+
+int display_draw(t_display *display) {
+
+ int x,y;
+
+#ifdef USE_NCURSES
+ mvprintw(0,0,"%s",display->screen);
+ for(y=0;y<display->max_y;y++)
+ for(x=0;x<display->max_x;x++)
+ mvaddch(y,x,*(display->screen+y*display->max_x+x));
+ refresh();
+#else
+ for(y=0;y<display->max_y;y++) {
+ for(x=0;x<display->max_x;x++)
+ printf("%c",*(display->screen+y*display->max_x+x));
+ printf("\n");
+ }
+#endif
+
+ return D_SUCCESS;
+}
+
+int display_draw_until_line(t_display *display,int line) {
+
+ int x,y;
+
+#ifdef USE_NCURSES
+ for(y=0;y<line;y++) {
+ for(x=0;x<display->max_x;x++)
+ mvaddch(y,x,*(display->screen+y*display->max_x+x));
+ refresh();
+ }
+#else
+ for(y=0;y<line;y++) {
+ for(x=0;x<display->max_x;x++)
+ printf("%c",*(display->screen+y*display->max_x+x));
+ printf("\n");
+ }
+#endif
+
+ return D_SUCCESS;
+}
+
+int display_set_cursor(t_display *display,int x,int y) {
+
+#ifdef USE_NCURSES
+ move(y,x);
+ refresh();
+#endif
+
+ return D_SUCCESS;
+}
+
+int display_clear_screen(t_display *display) {
+
+ memset(display->screen,0x20,display->max_x*display->max_y);
+
+ return D_SUCCESS;
+}
+
+int display_shutdown(t_display *display) {
+
+#ifdef USE_NCURSES
+ endwin();
+#endif
+
+ free(display->screen);
+
+ puts("[display] shutdown");
+
+ return D_SUCCESS;
+}
+
+int display_line(t_display *display,int X,int Y,int X_,int Y_,char sym) {
+
+ double m;
+ int x,y;
+
+ m=(Y_-Y)/(X_-X);
+
+ for(y=0;y<display->max_y;y++)
+ for(x=0;x<display->max_x;x++)
+ if((int)((x-X)*m+Y)==y) *(display->screen+y*display->max_x+x)=sym;
+
+ return D_SUCCESS;
+}
+
+int display_string(t_display *display,int x,int y,char *string,int len) {
+
+ if(len>display->max_x-x) return D_INV_STRING_LEN;
+
+ memcpy(display->screen+y*display->max_x+x,string,len);
+
+ return D_SUCCESS;
+}
+
+int display_string_vert(t_display *display,int x,int y,char *string,int len) {
+
+ int i;
+
+ if(len>display->max_y-y) return D_INV_STRING_LEN;
+ for(i=y*display->max_x+x;i<(y+len)*display->max_x+x;i+=display->max_x)
+ *(display->screen+i)=*(string++);
+
+ return D_SUCCESS;
+}
--- /dev/null
+/* display.h -- display headers */
+
+/* includes */
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/ioctl.h>
+#include <ncurses.h>
+
+/* defines */
+#define D_SUCCESS 1
+#define D_ERROR -1
+#define D_INV_STRING_LEN -2
+
+#define MAX_TERM_STRING 64
+
+#define CENTERED (1<<0)
+#define LEFT (1<<1)
+#define RIGHT (1<<2)
+
+/* display specific variables */
+typedef struct s_display {
+ int max_x;
+ int max_y;
+ unsigned char *screen;
+} t_display;
+
+/* function prototypes */
+int display_init(t_display *display);
+int display_draw(t_display *display);
+int display_draw_until_line(t_display *display,int line);
+int display_set_cursor(t_display *display,int x,int y);
+int display_clear_screen(t_display *display);
+int display_shutdown(t_display *display);
+int display_line(t_display *display,int X,int Y,int X_,int Y_,char sym);
+int display_string(t_display *display,int x,int y,char *string,int len);
+int display_string_vert(t_display *display,int x,int y,char *string,int len);
--- /dev/null
+/* event.c -- event management stuff
+ *
+ * author: hackbard@hackdaworld.dyndns.org
+ *
+ */
+
+#include "event.h"
+
+int event_init(t_event *event) {
+
+ write(2,"[event] initializing event system ...",37);
+
+ event->maxfd=0;
+
+ FD_ZERO(&(event->rfds));
+ FD_ZERO(&(event->rfds_o));
+ FD_ZERO(&(event->wfds));
+ FD_ZERO(&(event->wfds_o));
+
+ return E_SUCCESS;
+}
+
+int event_math(int fd,t_event *event,char rw,char ar) {
+
+ if(ar==ADD) {
+ if(rw==READ) FD_SET(fd,&(event->rfds_o));
+ else FD_SET(fd,&(event->wfds_o));
+ if(fd>event->maxfd) event->maxfd=fd;
+ } else {
+ if(rw==READ) FD_CLR(fd,&(event->rfds_o));
+ else FD_CLR(fd,&(event->wfds_o));
+ if(fd==event->maxfd) event->maxfd-=1;
+ }
+
+ printf("[event] %c fd %d to %c file descriptor set\n",ar==ADD?'+':'-',fd,
+ rw==READ?'r':'w');
+
+ return E_SUCCESS;
+}
+
+int event_start(t_event *event,void *ptr,
+ int (*callback0)(t_event *event,void *ptr),
+ int (*callback1)(t_event *event,void *ptr)) {
+
+ int s_ret;
+ struct timeval tv;
+
+ /* switch on event system */
+ event->status=ENABLED;
+
+ while(event->status&ENABLED) {
+
+ event->rfds=event->rfds_o;
+ event->wfds=event->wfds_o;
+ tv=event->timeout;
+
+ if((s_ret=select(event->maxfd+1,&(event->rfds),&(event->wfds),NULL,
+ &tv))==-1) {
+ perror("[event] select call");
+ return E_ERROR;
+ }
+
+ if(s_ret) {
+ /* 1+ fd(s) available for reading/writing */
+ if(callback0(event,ptr)==CALLBACK_ERROR) {
+ write(2,"[event] callback0 returned error",32);
+ return E_ERROR;
+ }
+ }
+
+ /* usual stuff to be executed */
+ if(callback1(event,ptr)==CALLBACK_ERROR) {
+ write(2,"[event] callback returned error",31);
+ return E_ERROR;
+ }
+
+ }
+
+ return E_SUCCESS;
+}
+
+int event_stop(t_event *event) {
+
+ write(2,"[event] shutdown",16);
+ event->status=DISABLED;
+
+ return E_SUCCESS;
+}
--- /dev/null
+/* event.h -- event headers */
+
+#ifndef EVENT_H
+#define EVENT_H
+
+/* includes */
+#include <stdio.h>
+#include <sys/select.h>
+#include <unistd.h>
+
+/* defines */
+
+/* return values */
+#define CALLBACK_ERROR -1
+#define E_ERROR -1
+#define E_SUCCESS 1
+
+/* event status */
+#define DISABLED 0
+#define ENABLED 1
+
+/* read write mode */
+#define READ 'r'
+#define WRITE 'w'
+/* add remove mode */
+#define ADD 'a'
+#define REMOVE 'r'
+
+/* event specific variables */
+typedef struct s_event {
+ int maxfd;
+ fd_set rfds,rfds_o;
+ fd_set wfds,wfds_o;
+ struct timeval timeout;
+ unsigned char status;
+} t_event;
+
+/* function prototypes */
+int event_init(t_event *event);
+int event_math(int fd,t_event *event,char rw,char ar);
+int event_start(t_event *event,void *ptr,
+ int (*callback0)(t_event *event,void *ptr),
+ int (*callback1)(t_event *event,void *ptr));
+int event_stop(t_event *event);
+
+#endif
--- /dev/null
+/* input.c -- input management stuff
+ *
+ * author: hackbard@hackdaworld.dyndns.org
+ *
+ */
+
+#include "input.h"
+
+int input_init(t_input *input) {
+
+ struct termios tios;
+ int size;
+
+ puts("[input] initializing input system ...");
+
+ // size=((input->mode&CONTENT_BUFFER)?MAX_CONTENT:1); <- ???
+ size=MAX_CONTENT;
+
+ if((input->content=(char *)malloc(size))==NULL) {
+ perror("[input] malloc call");
+ return I_ERROR;
+ }
+
+ memset(input->content,0,size);
+ input->c_count=0;
+
+ tcgetattr(0,&(input->tios));
+ tios=input->tios;
+
+ /* general settings */
+ tios.c_iflag&=ICRNL; /* \r -> \n */
+ tios.c_cc[VTIME]=0; /* no timeout */
+ tios.c_cc[VMIN]=1; /* 1 char for non-can. mode */
+
+ /* depending on used modes */
+ if(!(input->mode&LINE_BUFFERED)) tios.c_lflag&=(~ICANON);
+ if(!(input->mode&INPUT_ECHO)) tios.c_lflag&=(~ECHO);
+
+ tcsetattr(0,TCSANOW,&tios);
+
+ return I_SUCCESS;
+}
+
+int input_shutdown(t_input *input) {
+
+ free(input->content);
+ tcsetattr(0,TCSANOW,&(input->tios));
+ puts("[input] shutdown");
+
+ return I_SUCCESS;
+}
+
+int input_get_event(t_input *input,int (*callback)(t_input *input,void *ptr),
+ void *ptr) {
+
+ char data[MAX_CONTENT];
+ int count;
+
+ /* delete char counter if not buffered */
+ if(!(input->mode&CONTENT_BUFFER)) input->c_count=0;
+
+ if((count=read(0,data,MAX_CONTENT))==-1) {
+ perror("[input] read call");
+ return I_ERROR;
+ }
+
+ if(input->c_count>=MAX_CONTENT) {
+ puts("[input] max input length reached");
+ return I_ERROR;
+ }
+
+ strncpy(&(input->content[input->c_count]),data,count);
+ input->c_count+=count;
+
+ callback(input,ptr);
+
+ return I_SUCCESS;
+}
--- /dev/null
+/* input.h -- input headers */
+
+#ifndef INPUT_H
+#define INPUT_H
+
+/* includes */
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <errno.h>
+#include <termios.h>
+
+/* defines */
+#define I_SUCCESS 1
+#define I_ERROR -1
+
+#define MENUE (1<<0)
+#define CONNECTIONS (1<<1)
+
+#define MAX_CONTENT 128
+
+#define LINE_BUFFERED (1<<0)
+#define CONTENT_BUFFER (1<<1)
+#define INPUT_ECHO (1<<2)
+
+/* input specific variables */
+typedef struct s_input {
+ char *content;
+ int c_count;
+ unsigned char mode;
+ struct termios tios;
+} t_input;
+
+/* function prototypes */
+int input_init(t_input *input);
+int input_shutdown(t_input *input);
+int input_get_event(t_input *input,int (*callback)(t_input *input,void *ptr),
+ void *ptr);
+
+#endif
--- /dev/null
+/* network.c -- network management stuff
+ *
+ * author: hackbard@hackdaworld.dyndns.org
+ *
+ */
+
+#include "network.h"
+
+int network_init(t_net *net) {
+
+ struct sockaddr_in addr;
+ int true;
+
+ puts("[network] initializing network ...");
+
+ memset(net->connection,0,MAX_CONNECTIONS*sizeof(t_connection));
+ net->c_count=0;
+ net->sendmask=0;
+
+ if((net->l_fd=socket(AF_INET,SOCK_STREAM,0))==-1) {
+ perror("[network] socket call");
+ return N_ERROR;
+ }
+
+ memset(&addr,0,sizeof(struct sockaddr));
+ addr.sin_family=AF_INET;
+ addr.sin_port=htons(net->l_port);
+ addr.sin_addr.s_addr=INADDR_ANY;
+
+ if(bind(net->l_fd,(struct sockaddr *)&addr,
+ sizeof(struct sockaddr))==-1) {
+ /* try harder ... */
+ true=1;
+ if(setsockopt(net->l_fd,SOL_SOCKET,SO_REUSEADDR,&true,sizeof(true))==-1) {
+ perror("[network] setsockopt call");
+ return N_ERROR;
+ }
+ puts("[network] reused address");
+ }
+
+ if(listen(net->l_fd,MAX_LISTEN_QUEUE)==-1) {
+ perror("[network] listen call");
+ return N_ERROR;
+ }
+
+ printf("[network] listen on %s port %d\n",inet_ntoa(addr.sin_addr),
+ net->l_port);
+
+ return N_SUCCESS;
+}
+
+int network_shutdown(t_net *net) {
+
+ int channel;
+
+ for(channel=0;channel<MAX_CONNECTIONS;channel++)
+ if(net->connection[channel].status&C_SOCKET)
+ close(net->connection[channel].fd);
+
+ if(close(net->l_fd)==-1) {
+ perror("[network] close call");
+ return N_ERROR;
+ }
+
+ puts("[network] shutdown");
+
+ return N_SUCCESS;
+}
+
+int network_set_listen_port(t_net *net,in_port_t port) {
+
+ net->l_port=port;
+
+ return N_SUCCESS;
+}
+
+int network_manage_connection(t_net *net) {
+
+ int i;
+ struct sockaddr_in addr;
+
+ for(i=0;i<MAX_CONNECTIONS;i++) {
+
+ if(net->connection[i].status&C_IN_USE) {
+
+ if(net->connection[i].status&C_HANGUP) {
+ if(close(net->connection[i].fd)==-1) {
+ perror("[network] close call");
+ return N_E_CLOSE;
+ }
+ printf("[network] connection %d closed\n",i);
+ net->connection[i].status=0;
+ }
+
+ if(net->connection[i].status&C_INFO_A) {
+
+ if(!(net->connection[i].status&C_SOCKET)) {
+ if((net->connection[i].fd=socket(AF_INET,SOCK_STREAM,0))==-1) {
+ perror("[network] socket call");
+ return N_ERROR;
+ }
+ net->connection[i].status|=C_SOCKET;
+ }
+
+ if((!(net->connection[i].status&C_ESTABL))&&
+ (net->connection[i].status&C_SOCKET)) {
+
+ memset(&addr,0,sizeof(struct sockaddr));
+ addr.sin_family=AF_INET;
+ addr.sin_port=htons(net->connection[i].port);
+ if(!inet_aton(net->connection[i].ip,&(addr.sin_addr))) {
+ perror("[network] inet_aton call");
+ return N_ERROR;
+ }
+
+ if(connect(net->connection[i].fd,(struct sockaddr *)&addr,
+ sizeof(struct sockaddr))==-1) {
+ perror("[network] connect call");
+ return N_E_CONNECT;
+ }
+
+ printf("[network] established connection to ");
+ printf("%s port %d on channel %d\n",net->connection[i].ip,
+ net->connection[i].port,i);
+ net->connection[i].status|=C_ESTABL;
+
+ }
+
+ }
+
+ }
+
+ }
+
+ return N_SUCCESS;
+}
+
+int network_connect(t_net *net,int channel) {
+
+ if(net->connection[channel].status&C_IN_USE) {
+ printf("[network] connect failed, channel %02d in use\n",channel);
+ return N_E_IN_USE;
+ }
+ if(!(net->connection[channel].status&C_INFO_A)) {
+ printf("[network] connect failed, missing configuration for channel %02d\n",
+ channel);
+ return N_E_NO_INFO;
+ }
+
+ /* try connect & return result */
+ net->connection[channel].status|=C_IN_USE;
+ return(network_manage_connection(net)); /* could be other channel too */
+}
+
+int network_close(t_net *net,int channel) {
+
+ if(!(net->connection[channel].status&C_ESTABL)) {
+ printf("[network] close failed, channel %02d not active\n",channel);
+ return N_E_NC;
+ }
+
+ net->connection[channel].status|=C_HANGUP;
+ return(network_manage_connection(net)); /* could be other channel too */
+}
+
+int network_close_all(t_net *net) {
+
+ int channel;
+
+ for(channel=0;channel<MAX_CONNECTIONS;channel++)
+ if(net->connection[channel].status&C_ESTABL) network_close(net,channel);
+
+ return N_SUCCESS;
+}
+
+int network_set_connection_info(t_net *net,int channel,char *ip,int port) {
+
+ if(net->connection[channel].status&C_IN_USE) {
+ printf("[network] set connection failed, channel %02d in use\n",channel);
+ return N_E_IN_USE;
+ }
+
+ strncpy(net->connection[channel].ip,ip,IP_DIGITS);
+ net->connection[channel].port=port;
+ net->connection[channel].status|=C_INFO_A;
+
+ return N_SUCCESS;
+}
+
+int network_select(t_net *net,int channel) {
+
+ int mask;
+
+ if(channel==MAX_CONNECTIONS) mask=0xffffffff;
+ else mask=(1<<channel);
+ net->sendmask|=mask;
+
+ return N_SUCCESS;
+}
+
+int network_deselect(t_net *net,int channel) {
+
+ int mask;
+
+ if(channel==MAX_CONNECTIONS) mask=0;
+ else mask=~(1<<channel);
+ net->sendmask&=mask;
+
+ return N_SUCCESS;
+}
+
+int network_manage_incoming(t_net *net) {
+
+ int channel;
+ struct sockaddr_in addr;
+ int len;
+
+ for(channel=0;channel<MAX_CONNECTIONS;channel++) {
+ if(!(net->connection[channel].status&C_IN_USE)) {
+ if((net->connection[channel].fd=accept(net->l_fd,
+ (struct sockaddr *)&addr,
+ &len))==-1) {
+ perror("[network] accept call");
+ return N_E_ACCEPT;
+ }
+ strncpy(net->connection[channel].ip,inet_ntoa(addr.sin_addr),IP_DIGITS);
+ net->connection[channel].port=ntohs(addr.sin_port);
+ net->connection[channel].status=C_IN_USE|C_INFO_A|C_SOCKET|C_ESTABL;
+ printf("[network] established connection from %s port %d on channel %d\n",
+ net->connection[channel].ip,net->connection[channel].port,channel);
+ return channel;
+ }
+ }
+
+ puts("[network] maximum connections reached");
+ return N_E_MAXC;
+}
+
+int network_send(int fd,unsigned char *data,int datasize) {
+
+ int count,left;
+
+ count=0;
+ left=datasize;
+
+ while(left) {
+ if((count=write(fd,data+datasize-left,left))==-1) {
+ perror("[network] write call");
+ return N_ERROR;
+ }
+ left-=count;
+ }
+
+ return N_SUCCESS;
+}
+
+int network_receive(int fd,unsigned char *data,int datasize) {
+
+ int count;
+
+ if((count=read(fd,data,datasize))==-1) {
+ perror("[network] read call");
+ return N_ERROR;
+ }
+
+ return count;
+}
+
+int network_udp_listen_init(t_net *net) {
+
+ struct sockaddr_in addr;
+ int true;
+
+ if((net->l_udp_fd=socket(AF_INET,SOCK_DGRAM,0))==-1) {
+ perror("[network] socket call (udp-receive)");
+ return N_ERROR;
+ }
+
+ memset(&addr,0,sizeof(struct sockaddr));
+ addr.sin_family=AF_INET;
+ addr.sin_port=htons(net->l_udp_port);
+ addr.sin_addr.s_addr=INADDR_ANY;
+ if(bind(net->l_udp_fd,(struct sockaddr *)&addr,sizeof(struct sockaddr))==-1) {
+ /* try harder ... */
+ true=1;
+ if(setsockopt(net->l_udp_fd,SOL_SOCKET,SO_REUSEADDR,
+ &true,sizeof(true))==-1) {
+ perror("[network] setsockopt call (udp)");
+ return N_ERROR;
+ }
+ puts("[network] reused address (udp)");
+ }
+
+ printf("[network] listening on port %d (udp)\n",net->l_udp_port);
+
+ if((net->s_udp_fd=socket(AF_INET,SOCK_DGRAM,0))==-1) {
+ perror("[network] socket call (udp-send)");
+ return N_ERROR;
+ }
+
+ return N_SUCCESS;
+}
+
+int network_udp_receive(t_net *net,int channel, unsigned char *data,int count) {
+
+ struct sockaddr_in addr;
+ socklen_t len;
+
+ if((count=recvfrom(net->l_udp_fd,data,count,0,
+ (struct sockaddr *)&addr,&len))==-1) {
+ perror("[network] recvfrom call");
+ return N_ERROR;
+ }
+
+ if(strncmp(net->connection[channel].ip,inet_ntoa(addr.sin_addr),IP_DIGITS)) {
+ printf("[network] packet from unknown: %s\n",inet_ntoa(addr.sin_addr));
+ return N_UDP_WRONG_SENDER;
+ }
+
+ return N_SUCCESS;
+}
+
+int network_udp_send(t_net *net,int channel, unsigned char *data,int size) {
+
+ int count,left;
+ struct sockaddr_in addr;
+
+ count=0;
+ left=count;
+
+ memset(&addr,0,sizeof(struct sockaddr));
+ addr.sin_family=AF_INET;
+ addr.sin_port=htons(net->l_udp_port);
+ inet_aton(net->connection[channel].ip,&(addr.sin_addr));
+
+ while(left) {
+ if((count=sendto(net->s_udp_fd,data+size-left,left,0,
+ (struct sockaddr *)&addr,sizeof(struct sockaddr)))==-1) {
+ perror("[network] sendto call");
+ return N_ERROR;
+ }
+ left-=count;
+ }
+
+ return N_SUCCESS;
+}
+
+int network_udp_shutdown(t_net *net) {
+
+ if(close(net->l_udp_fd)==-1) {
+ perror("[network] close call (udp-receive)");
+ return N_ERROR;
+ }
+
+ if(close(net->s_udp_fd)==-1) {
+ perror("[network] close call (udp-send)");
+ return N_ERROR;
+ }
+
+ return N_SUCCESS;
+}
--- /dev/null
+/* network.h -- network headers */
+
+#ifndef NETWORK_H
+#define NETWORK_H
+
+/* includes */
+#include <stdio.h>
+#include <errno.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <unistd.h>
+
+/* net specific includes */
+#include <netinet/in.h>
+#include <arpa/inet.h>
+
+/* defines */
+#define MAX_CONNECTIONS 32
+#define MAX_NIC_DEVICE 32
+
+#define IP_DIGITS 16
+#define C_IN_USE (1<<0)
+#define C_INFO_A (1<<1)
+#define C_SOCKET (1<<2)
+#define C_ESTABL (1<<3)
+#define C_HANGUP (1<<4)
+
+#define SEND_N_MAX 128
+
+#define N_SUCCESS 1
+#define N_ERROR -1
+#define N_E_IN_USE -2
+#define N_E_NO_INFO -3
+#define N_E_CLOSE -4
+#define N_E_CONNECT -5
+#define N_E_NC -6
+#define N_E_ACCEPT -7
+#define N_E_MAXC -8
+
+#define N_UDP_WRONG_SENDER -9
+
+#define MAX_LISTEN_QUEUE 32
+
+/* net specific variables */
+typedef struct s_connection {
+ int fd;
+ char ip[IP_DIGITS];
+ in_port_t port;
+ unsigned char status;
+ unsigned short cap; /* capabilities */
+} t_connection;
+
+typedef struct s_net {
+ int l_fd; /* fd for tcp conn */
+ int l_udp_fd; /* fd for udp data receive */
+ int s_udp_fd; /* fd for udp data send */
+ in_port_t l_port; /* tcp port */
+ int l_udp_port; /* udp listen port */
+ unsigned short cap;
+ /* limited connections by now -- replaced by list management later */
+ int c_count;
+ t_connection connection[MAX_CONNECTIONS];
+ unsigned int sendmask; /* 32 bits for maximum of 32 connections */
+ char nic[MAX_NIC_DEVICE];
+} t_net;
+
+/* function prototypes */
+int network_init(t_net *net);
+int network_shutdown(t_net *net);
+int network_set_listen_port(t_net *net,in_port_t port);
+int network_manage_connection(t_net *net);
+int network_connect(t_net *net,int channel);
+int network_close(t_net *net,int channel);
+int network_close_all(t_net *net);
+int network_set_connection_info(t_net *net,int channel,char *ip,int port);
+int network_select(t_net *net,int channel);
+int network_deselect(t_net *net,int channel);
+int network_manage_incoming(t_net *net);
+int network_send(int fd,unsigned char *data,int datasize);
+int network_receive(int fd,unsigned char *data,int datasize);
+int network_udp_listen_init(t_net *net);
+int network_udp_receive(t_net *net,int channel, unsigned char *data,int count);
+int network_udp_send(t_net *net,int channel, unsigned char *data,int size);
+int network_udp_shutdown(t_net *net);
+
+#endif