4f02370fbd60d934d027c982cd602c3f3279d86b
[my-code/ivac.git] / src / inet.c
1 /* inet.c -- network management stuff
2  *
3  * author: hackbard@hackdaworld.dyndns.org
4  *
5  */
6
7 #include "inet.h"
8
9 int network_init(t_ivac *ivac) {
10   
11   struct sockaddr_in addr;
12  
13   puts("[ivac] inet: initializing network ...");
14
15   memset(ivac->net.connection,0,MAX_CONNECTIONS*sizeof(t_connection));
16   ivac->net.c_count=0;
17   ivac->net.sendmask=0;
18
19   if((ivac->net.l_fd=socket(AF_INET,SOCK_STREAM,0))==-1) {
20     perror("[ivac] inet.c: socket call");
21     return ERROR;
22   }
23
24   memset(&addr,0,sizeof(struct sockaddr));
25   addr.sin_family=AF_INET;
26   addr.sin_port=htons(ivac->net.l_port);
27   addr.sin_addr.s_addr=INADDR_ANY;
28
29   if(bind(ivac->net.l_fd,(struct sockaddr *)&addr,
30           sizeof(struct sockaddr))==-1) {
31     perror("[ivac] inet.c: bind call");
32     return ERROR;
33   }
34
35   printf("[ivac] inet: listen on %s port %d.\n",inet_ntoa(addr.sin_addr)
36                                                ,ivac->net.l_port);
37
38   return SUCCESS;
39 }
40
41 int network_manage_connection(t_ivac *ivac) {
42
43   int i;
44   struct sockaddr_in addr;
45   
46   for(i=0;i<MAX_CONNECTIONS;i++) {
47
48     if(ivac->net.connection[i].status&C_IN_USE) {
49
50       if(ivac->net.connection[i].status&C_HANGUP) {
51         if(close(ivac->net.connection[i].fd)==-1) {
52           perror("[ivac] inet.c: close call");
53           return ERROR;
54         }
55         ivac->net.connection[i].status=0;
56       }
57
58       if(ivac->net.connection[i].status&C_INFO_A) {
59
60         if(!ivac->net.connection[i].status&C_SOCKET) {
61           if((ivac->net.connection[i].fd=socket(AF_INET,SOCK_STREAM,0))==-1) {
62             perror("[ivac] inet.c: socket call");
63             return ERROR;
64           }
65         }
66
67         if(!ivac->net.connection[i].status&C_ESTABL) {
68
69           memset(&addr,0,sizeof(struct sockaddr));
70           addr.sin_family=AF_INET;
71           addr.sin_port=htons(ivac->net.connection[i].port);
72           if(!inet_aton(ivac->net.connection[i].ip,&(addr.sin_addr))) {
73             perror("[ivac] inet.c: inet_aton call");
74             return ERROR;
75           }
76           
77           if(connect(ivac->net.connection[i].fd,(struct sockaddr *)&addr,
78                      sizeof(struct sockaddr))==-1) {
79             perror("[ivac] inet.c: connect call");
80             return ERROR;
81           }
82
83         }
84
85       }
86
87     }
88
89   }
90
91   return SUCCESS;
92 }
93
94 int network_manage_incoming(t_ivac *ivac) {
95
96   int i;
97   struct sockaddr_in addr;
98   int len;
99
100   for(i=0;i<MAX_CONNECTIONS;i++) {
101     if(!ivac->net.connection[i].status&C_IN_USE) {
102       if((ivac->net.connection[i].fd=accept(ivac->net.l_fd,
103                                             (struct sockaddr *)&addr,
104                                             &len))==-1) {
105         perror("[ivac] inet.c: accept call");
106         return ERROR;
107       }
108       strncpy(ivac->net.connection[i].ip,inet_ntoa(addr.sin_addr),IP_DIGITS);
109       ivac->net.connection[i].port=ntohs(addr.sin_port);
110       ivac->net.connection[i].status=C_IN_USE|C_INFO_A|C_SOCKET|C_ESTABL;
111       return i;
112     }
113   }
114
115   puts("[ivac] inet: maximum connections reached");
116   return ERROR;
117 }
118  
119 int network_send(int fd,unsigned char *data,int datasize) {
120
121   int count,left;
122
123   count=0;
124   left=datasize;
125
126   while(left) {
127     if((count=write(fd,data+datasize-left,left))==-1) {
128       perror("[ivac] inet.c: write call");
129       return ERROR;
130     }
131     left-=count;
132   }
133
134   return SUCCESS;
135 }
136
137 int network_receive(int fd,unsigned char *data,int datasize) {
138
139   int count,retval;
140
141   retval=1;
142   count=0;
143
144   while(retval) {
145     if((retval=read(fd,data+count,datasize-count))==-1) {
146       perror("[ivac] inet.c: read call");
147       return ERROR;
148     }
149     count+=retval;
150   }
151
152   return count;
153 }
154
155 int send_info(int fd,t_ivac *ivac) {
156
157   char data[SEND_I_MAX];
158   int size;
159
160   size=strlen(ivac->name);
161
162   data[0]=SEND_I_NAME;
163   data[1]=size;
164   strncpy(data+2,ivac->name,size);
165   size+=2;
166
167   data[size+1]=SEND_I_CAP;
168   data[size+2]=sizeof(unsigned char);
169   data[size+3]=ivac->net.cap;
170   size+=(sizeof(unsigned char)+2);
171
172   data[size+1]=SEND_I_AVCAP;
173   data[size+2]=sizeof(unsigned short);
174   data[size+2+sizeof(unsigned short)];
175   size+=(sizeof(unsigned short)+2);
176
177   if(network_send(fd,data,size)==ERROR) {
178     puts("[ivac] inet.c: send_info failed");
179     return ERROR;
180   }
181
182   return SUCCESS;
183 }
184
185 int receive_info(int i,t_ivac *ivac) {
186
187   char data[CHAR_USERNAME+2];
188   int count,length;
189
190   if((length=network_receive(ivac->net.connection[i].fd,
191                              data,SEND_I_MAX))==ERROR) {
192     puts("[ivac] inet.c: receive_info failed");
193     return ERROR;
194   }
195
196   while(length-count) {
197     switch(data[count]) {
198       case SEND_I_NAME:
199         strncpy(ivac->net.connection[i].name,data[count+2],data[count+1]);
200         ivac->net.connection[i].name[data[count+2]]='\0';
201         count+=(data[count+2]+2);
202         break;
203       case SEND_I_G_CAP:
204         ivac->net.connection[i].cap=data[count+4];
205         count+=(sizeof(unsigned char)+2);
206         break;
207       case SEND_I_AV_CAP:
208         ivac->net.connection[i].avcap=data[count+3]<<8;
209         ivac->net.connection[i].avcap|=data[count+4];
210         count+=(sizeof(unsigned short)+2);
211         break;
212       default:
213         puts("[ivac] inet.c: receive_info, unknown character");
214         return ERROR;
215     }
216   }
217     
218   return SUCCESS;
219 }