From 24edc387e6e88c32c6142f397ee891746eed62e3 Mon Sep 17 00:00:00 2001 From: hackbard Date: Wed, 23 Jun 2004 22:56:02 +0000 Subject: [PATCH 1/1] initial checkin --- CHANGELOG | 6 + audio/audio.c | 123 ++++++++++++++++ audio/audio.h | 53 +++++++ display/display.c | 150 +++++++++++++++++++ display/display.h | 37 +++++ event/event.c | 88 +++++++++++ event/event.h | 46 ++++++ input/input.c | 78 ++++++++++ input/input.h | 41 ++++++ network/network.c | 361 ++++++++++++++++++++++++++++++++++++++++++++++ network/network.h | 87 +++++++++++ 11 files changed, 1070 insertions(+) create mode 100644 CHANGELOG create mode 100644 audio/audio.c create mode 100644 audio/audio.h create mode 100644 display/display.c create mode 100644 display/display.h create mode 100644 event/event.c create mode 100644 event/event.h create mode 100644 input/input.c create mode 100644 input/input.h create mode 100644 network/network.c create mode 100644 network/network.h diff --git a/CHANGELOG b/CHANGELOG new file mode 100644 index 0000000..b243c39 --- /dev/null +++ b/CHANGELOG @@ -0,0 +1,6 @@ +*) 2004-06-24 + + - initial checkin: audio, display, event, input, network + (used for my-code/ivac) + +################################################################################ diff --git a/audio/audio.c b/audio/audio.c new file mode 100644 index 0000000..9c8ca4a --- /dev/null +++ b/audio/audio.c @@ -0,0 +1,123 @@ +/* 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; +} diff --git a/audio/audio.h b/audio/audio.h new file mode 100644 index 0000000..33e90cb --- /dev/null +++ b/audio/audio.h @@ -0,0 +1,53 @@ +/* audio.h -- audio headers */ + +#ifndef AUDIO_H +#define AUDIO_H + +/* includes */ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* 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 diff --git a/display/display.c b/display/display.c new file mode 100644 index 0000000..a925e3a --- /dev/null +++ b/display/display.c @@ -0,0 +1,150 @@ +/* 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;ymax_y;y++) + for(x=0;xmax_x;x++) + mvaddch(y,x,*(display->screen+y*display->max_x+x)); + refresh(); +#else + for(y=0;ymax_y;y++) { + for(x=0;xmax_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;ymax_x;x++) + mvaddch(y,x,*(display->screen+y*display->max_x+x)); + refresh(); + } +#else + for(y=0;ymax_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;ymax_y;y++) + for(x=0;xmax_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; +} diff --git a/display/display.h b/display/display.h new file mode 100644 index 0000000..29cf6c9 --- /dev/null +++ b/display/display.h @@ -0,0 +1,37 @@ +/* display.h -- display headers */ + +/* includes */ +#include +#include +#include +#include +#include + +/* 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); diff --git a/event/event.c b/event/event.c new file mode 100644 index 0000000..455921d --- /dev/null +++ b/event/event.c @@ -0,0 +1,88 @@ +/* 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; +} diff --git a/event/event.h b/event/event.h new file mode 100644 index 0000000..03994c5 --- /dev/null +++ b/event/event.h @@ -0,0 +1,46 @@ +/* event.h -- event headers */ + +#ifndef EVENT_H +#define EVENT_H + +/* includes */ +#include +#include +#include + +/* 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 diff --git a/input/input.c b/input/input.c new file mode 100644 index 0000000..86dac62 --- /dev/null +++ b/input/input.c @@ -0,0 +1,78 @@ +/* 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; +} diff --git a/input/input.h b/input/input.h new file mode 100644 index 0000000..6efcf6e --- /dev/null +++ b/input/input.h @@ -0,0 +1,41 @@ +/* input.h -- input headers */ + +#ifndef INPUT_H +#define INPUT_H + +/* includes */ +#include +#include +#include +#include +#include +#include + +/* 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 diff --git a/network/network.c b/network/network.c new file mode 100644 index 0000000..053e309 --- /dev/null +++ b/network/network.c @@ -0,0 +1,361 @@ +/* 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;channelconnection[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;iconnection[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;channelconnection[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<sendmask|=mask; + + return N_SUCCESS; +} + +int network_deselect(t_net *net,int channel) { + + int mask; + + if(channel==MAX_CONNECTIONS) mask=0; + else mask=~(1<sendmask&=mask; + + return N_SUCCESS; +} + +int network_manage_incoming(t_net *net) { + + int channel; + struct sockaddr_in addr; + int len; + + for(channel=0;channelconnection[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; +} diff --git a/network/network.h b/network/network.h new file mode 100644 index 0000000..079cea3 --- /dev/null +++ b/network/network.h @@ -0,0 +1,87 @@ +/* network.h -- network headers */ + +#ifndef NETWORK_H +#define NETWORK_H + +/* includes */ +#include +#include +#include +#include +#include +#include + +/* net specific includes */ +#include +#include + +/* 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 -- 2.39.2