]> hackdaworld.org Git - my-code/api.git/commitdiff
initial checkin
authorhackbard <hackbard>
Wed, 23 Jun 2004 22:56:02 +0000 (22:56 +0000)
committerhackbard <hackbard>
Wed, 23 Jun 2004 22:56:02 +0000 (22:56 +0000)
CHANGELOG [new file with mode: 0644]
audio/audio.c [new file with mode: 0644]
audio/audio.h [new file with mode: 0644]
display/display.c [new file with mode: 0644]
display/display.h [new file with mode: 0644]
event/event.c [new file with mode: 0644]
event/event.h [new file with mode: 0644]
input/input.c [new file with mode: 0644]
input/input.h [new file with mode: 0644]
network/network.c [new file with mode: 0644]
network/network.h [new file with mode: 0644]

diff --git a/CHANGELOG b/CHANGELOG
new file mode 100644 (file)
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 (file)
index 0000000..9c8ca4a
--- /dev/null
@@ -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 (file)
index 0000000..33e90cb
--- /dev/null
@@ -0,0 +1,53 @@
+/* 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
diff --git a/display/display.c b/display/display.c
new file mode 100644 (file)
index 0000000..a925e3a
--- /dev/null
@@ -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;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;
+}
diff --git a/display/display.h b/display/display.h
new file mode 100644 (file)
index 0000000..29cf6c9
--- /dev/null
@@ -0,0 +1,37 @@
+/* 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);
diff --git a/event/event.c b/event/event.c
new file mode 100644 (file)
index 0000000..455921d
--- /dev/null
@@ -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 (file)
index 0000000..03994c5
--- /dev/null
@@ -0,0 +1,46 @@
+/* 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
diff --git a/input/input.c b/input/input.c
new file mode 100644 (file)
index 0000000..86dac62
--- /dev/null
@@ -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 (file)
index 0000000..6efcf6e
--- /dev/null
@@ -0,0 +1,41 @@
+/* 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
diff --git a/network/network.c b/network/network.c
new file mode 100644 (file)
index 0000000..053e309
--- /dev/null
@@ -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;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;
+}
diff --git a/network/network.h b/network/network.h
new file mode 100644 (file)
index 0000000..079cea3
--- /dev/null
@@ -0,0 +1,87 @@
+/* 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