Browse code

make server reply to ping with action taken (new/updated...)

Dario Rodriguez authored on 05/05/2014 12:44:02
Showing 1 changed files
... ...
@@ -37,13 +37,20 @@ typedef struct urusai {
37 37
         client *clients;
38 38
 } urusai;
39 39
 
40
+typedef enum seenaction {
41
+	seen_error=0,
42
+	seen_new,
43
+	seen_updated,
44
+	seen_nochange
45
+} seenaction;
46
+
40 47
 static int signal_init(int signum, void (*fn)(int));
41 48
 static void sigint(int signum);
42 49
 volatile int sigint_flag=0;
43 50
 
44 51
 urusai *urusai_init(void);
45 52
 void urusai_free(urusai *u);
46
-client *urusai_clientseen(urusai *u, char *id, struct sockaddr_in *addr);
53
+client *urusai_clientseen(urusai *u, char *id, struct sockaddr_in *addr, seenaction *seen);
47 54
 int urusai_clientdeleteold(urusai *u, int timeout);
48 55
 client *urusai_clientget(urusai *u, char *id);
49 56
 int urusai_send(urusai *u, char *outbuf, int outbuf_used, client *destclient);
... ...
@@ -62,6 +69,7 @@ main(int argc, char *argv[])
62 69
         urusai *u;
63 70
         client *origclient, *destclient;
64 71
         char *serial,*origid,*destid,*cmd,*contents;
72
+	seenaction seen;	
65 73
         if((u=urusai_init())==NULL) {
66 74
                 printf("ERROR: Couldn'n get/bind socket or insufficient memory\n");
67 75
                 return(1);
... ...
@@ -69,15 +77,16 @@ main(int argc, char *argv[])
69 77
         sigint_flag=0;
70 78
         signal_init(SIGINT,sigint);
71 79
         while(!sigint_flag) {
80
+		memset(&clientaddr,0,sizeof(clientaddr));
72 81
                 clientaddr_len=sizeof(clientaddr);
73 82
                 if((inbuf_used=recvfrom(u->fd,inbuf,sizeof(inbuf),0,(struct sockaddr *)&clientaddr,&clientaddr_len))==-1)
74 83
                         continue; /* interrupted by signal */
75 84
                 if(msg_parse(inbuf,inbuf_used,&serial,&origid,&destid,&cmd,&contents)!=0)
76 85
                         continue;
77
-                if((origclient=urusai_clientseen(u,origid,&clientaddr))==NULL)
86
+                if((origclient=urusai_clientseen(u,origid,&clientaddr,&seen))==NULL)
78 87
                         continue;
79 88
                 if(strcmp(cmd,"ping")==0) {
80
-                        outbuf_used=msg_compose(outbuf, sizeof(outbuf), serial, NULL, origid,"pong",NULL);
89
+                        outbuf_used=msg_compose(outbuf, sizeof(outbuf), serial, NULL, origid,"pong",(seen==seen_new)?"new":(seen==seen_updated)?"updated":(seen==seen_nochange)?"nochange":NULL);
81 90
                         urusai_send(u,outbuf,outbuf_used,origclient);
82 91
                 } else if(strcmp(cmd,"message")==0) {
83 92
                         if((destclient=urusai_clientget(u,destid))==NULL) {
... ...
@@ -154,12 +163,15 @@ urusai_free(urusai *u)
154 163
 }
155 164
 
156 165
 client *
157
-urusai_clientseen(urusai *u, char *id, struct sockaddr_in *addr)
166
+urusai_clientseen(urusai *u, char *id, struct sockaddr_in *addr,seenaction *seen)
158 167
 {
159 168
         int i,ifree;
160 169
         client *c;
161
-        if(u==NULL)
170
+        if(u==NULL || id==NULL || addr==NULL || seen==NULL) {
171
+		if(seen!=NULL)
172
+			*seen=seen_error;
162 173
                 return(NULL);
174
+	}
163 175
         if(u->numclients==u->sizeclients) {
164 176
                 client *newc;
165 177
                 if((newc=realloc(u->clients,sizeof(client)*(u->sizeclients+CLIENTBLOCK)))==NULL)
... ...
@@ -176,13 +188,21 @@ urusai_clientseen(urusai *u, char *id, struct sockaddr_in *addr)
176 188
                         break;
177 189
         }
178 190
         if(i==u->sizeclients) {
179
-                if(ifree==-1)
191
+                if(ifree==-1) {
192
+			*seen=seen_error;
180 193
                         return(NULL);
194
+		}
181 195
                 i=ifree;
182 196
                 c=u->clients+i;
183 197
                 strncpy(c->id,id,sizeof(c->id));
184 198
                 c->id[sizeof(c->id)-1]='\0';
185
-        }
199
+		*seen=seen_new;
200
+        } else {
201
+		if(memcmp(&(c->addr),addr,sizeof(c->addr))==0)
202
+			*seen=seen_nochange;
203
+		else
204
+			*seen=seen_updated;
205
+	}
186 206
         c->lastrecv=time(NULL);
187 207
         memcpy(&(c->addr),addr,sizeof(c->addr));
188 208
         return(c);
Browse code

Initial server implementation without encryption and test client in tcl

Dario Rodriguez authored on 05/05/2014 12:17:18
Showing 1 changed files
1 1
new file mode 100644
... ...
@@ -0,0 +1,291 @@
1
+/*
2
+ * urusaiserver.c
3
+ *
4
+ * UDP notificator server implementing simple messaging.
5
+ *
6
+ * Author: Dario Rodriguez dario@softhome.net
7
+ */
8
+
9
+#include <stdio.h>
10
+#include <stdlib.h>
11
+#include <unistd.h>
12
+#include <string.h>
13
+#include <arpa/inet.h>
14
+#include <sys/types.h>
15
+#include <sys/socket.h>
16
+#include <signal.h>
17
+#include <time.h>
18
+#include <errno.h>
19
+
20
+#define SERVERPORT 20245
21
+#define BUFLEN 2048
22
+#define MAXID 32
23
+#define CLIENTBLOCK 128
24
+#define MAXPACKETSIZE 1300
25
+
26
+typedef struct client {
27
+        struct sockaddr_in addr;
28
+        time_t lastrecv;
29
+        char id[MAXID];
30
+} client;
31
+
32
+typedef struct urusai {
33
+        int fd;
34
+        struct sockaddr_in myaddr;
35
+        int numclients;
36
+        int sizeclients;
37
+        client *clients;
38
+} urusai;
39
+
40
+static int signal_init(int signum, void (*fn)(int));
41
+static void sigint(int signum);
42
+volatile int sigint_flag=0;
43
+
44
+urusai *urusai_init(void);
45
+void urusai_free(urusai *u);
46
+client *urusai_clientseen(urusai *u, char *id, struct sockaddr_in *addr);
47
+int urusai_clientdeleteold(urusai *u, int timeout);
48
+client *urusai_clientget(urusai *u, char *id);
49
+int urusai_send(urusai *u, char *outbuf, int outbuf_used, client *destclient);
50
+
51
+
52
+int msg_parse(char *inbuf, int inbuf_used,char **serial,char **origid,char **destid,char **cmd, char **contents);
53
+int msg_compose(char *outbuf, int bufsize, char *serial, char *origid, char *destid, char *cmd, char *contents);
54
+
55
+int
56
+main(int argc, char *argv[])
57
+{
58
+        char inbuf[BUFLEN],outbuf[BUFLEN];;
59
+        int inbuf_used,outbuf_used;
60
+        struct sockaddr_in clientaddr;
61
+        socklen_t clientaddr_len;
62
+        urusai *u;
63
+        client *origclient, *destclient;
64
+        char *serial,*origid,*destid,*cmd,*contents;
65
+        if((u=urusai_init())==NULL) {
66
+                printf("ERROR: Couldn'n get/bind socket or insufficient memory\n");
67
+                return(1);
68
+        }
69
+        sigint_flag=0;
70
+        signal_init(SIGINT,sigint);
71
+        while(!sigint_flag) {
72
+                clientaddr_len=sizeof(clientaddr);
73
+                if((inbuf_used=recvfrom(u->fd,inbuf,sizeof(inbuf),0,(struct sockaddr *)&clientaddr,&clientaddr_len))==-1)
74
+                        continue; /* interrupted by signal */
75
+                if(msg_parse(inbuf,inbuf_used,&serial,&origid,&destid,&cmd,&contents)!=0)
76
+                        continue;
77
+                if((origclient=urusai_clientseen(u,origid,&clientaddr))==NULL)
78
+                        continue;
79
+                if(strcmp(cmd,"ping")==0) {
80
+                        outbuf_used=msg_compose(outbuf, sizeof(outbuf), serial, NULL, origid,"pong",NULL);
81
+                        urusai_send(u,outbuf,outbuf_used,origclient);
82
+                } else if(strcmp(cmd,"message")==0) {
83
+                        if((destclient=urusai_clientget(u,destid))==NULL) {
84
+                                outbuf_used=msg_compose(outbuf, sizeof(outbuf), serial, NULL, origid,"messageerror","destid_unknown");
85
+                                urusai_send(u,outbuf,outbuf_used,origclient);
86
+                        } else {
87
+                                outbuf_used=msg_compose(outbuf, sizeof(outbuf), serial, origid, destid,"message",contents);
88
+                                urusai_send(u,outbuf,outbuf_used,destclient);
89
+                        }
90
+                } else if(strcmp(cmd,"receipt")==0) {
91
+                        if((destclient=urusai_clientget(u,destid))==NULL) {
92
+                                outbuf_used=msg_compose(outbuf, sizeof(outbuf), serial, NULL, origid,"receipterror","destid_unknown");
93
+                                urusai_send(u,outbuf,outbuf_used,origclient);
94
+                        } else {
95
+                                outbuf_used=msg_compose(outbuf, sizeof(outbuf), serial, origid, destid,"receipt",contents);
96
+                                urusai_send(u,outbuf,outbuf_used,destclient);
97
+                        }
98
+                }
99
+        }
100
+        urusai_free(u),u=NULL;
101
+        return(0);
102
+}
103
+
104
+static int
105
+signal_init(int signum, void (*fn)(int))
106
+{
107
+        struct sigaction sa;
108
+        sa.sa_handler=fn;
109
+        sigemptyset(&sa.sa_mask);
110
+        sa.sa_flags=0;
111
+        return(sigaction(signum,&sa,0));
112
+}
113
+
114
+static void
115
+sigint(int signum)
116
+{
117
+        sigint_flag=1;
118
+}
119
+
120
+urusai *
121
+urusai_init(void)
122
+{
123
+        urusai *u;
124
+        if((u=malloc(sizeof(urusai)))==NULL)
125
+                return(NULL);
126
+        memset(u,0,sizeof(urusai));
127
+        if((u->fd=socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP))==-1) {
128
+                urusai_free(u),u=NULL;
129
+                return(NULL);
130
+        }
131
+        u->myaddr.sin_family=AF_INET;
132
+        u->myaddr.sin_port=htons(SERVERPORT);
133
+        u->myaddr.sin_addr.s_addr=htonl(INADDR_ANY);
134
+        if(bind(u->fd,(struct sockaddr *)&(u->myaddr),sizeof(u->myaddr))==-1) {
135
+                urusai_free(u),u=NULL;
136
+                return(NULL);
137
+        }
138
+        return(u);
139
+}
140
+
141
+void
142
+urusai_free(urusai *u)
143
+{
144
+        if(u==NULL)
145
+                return;
146
+        if(u->fd!=-1)
147
+                close(u->fd),u->fd=-1;
148
+        if(u->clients) {
149
+                free(u->clients),u->clients=NULL;
150
+                u->numclients=0;
151
+                u->sizeclients=0;
152
+        }
153
+        free(u),u=NULL;
154
+}
155
+
156
+client *
157
+urusai_clientseen(urusai *u, char *id, struct sockaddr_in *addr)
158
+{
159
+        int i,ifree;
160
+        client *c;
161
+        if(u==NULL)
162
+                return(NULL);
163
+        if(u->numclients==u->sizeclients) {
164
+                client *newc;
165
+                if((newc=realloc(u->clients,sizeof(client)*(u->sizeclients+CLIENTBLOCK)))==NULL)
166
+                        return(NULL);
167
+                u->clients=newc;
168
+                memset(u->clients+u->sizeclients,0,CLIENTBLOCK*sizeof(client));
169
+                u->sizeclients+=CLIENTBLOCK;
170
+        }
171
+        for(i=0,ifree=-1;i<u->sizeclients;i++) {
172
+                c=u->clients+i;
173
+                if(c->id[0]=='\0' && ifree==-1)
174
+                        ifree=i;
175
+                if(strcmp(id,c->id)==0)
176
+                        break;
177
+        }
178
+        if(i==u->sizeclients) {
179
+                if(ifree==-1)
180
+                        return(NULL);
181
+                i=ifree;
182
+                c=u->clients+i;
183
+                strncpy(c->id,id,sizeof(c->id));
184
+                c->id[sizeof(c->id)-1]='\0';
185
+        }
186
+        c->lastrecv=time(NULL);
187
+        memcpy(&(c->addr),addr,sizeof(c->addr));
188
+        return(c);
189
+}
190
+
191
+int
192
+urusai_clientdeleteold(urusai *u, int timeout)
193
+{
194
+        time_t cuttime;
195
+        int i;
196
+        client *c;
197
+        if(u==NULL)
198
+                return(-1);
199
+        cuttime=time(NULL)-timeout;
200
+        for(i=0;i<u->sizeclients;i++) {
201
+                c=u->clients+i;
202
+                if(c->id[0]=='\0' || c->lastrecv>cuttime)
203
+                        continue;
204
+                memset(c,0,sizeof(client));
205
+        }
206
+        return(0);
207
+}
208
+
209
+client *
210
+urusai_clientget(urusai *u, char *id)
211
+{
212
+        int i;
213
+        client *c;
214
+        if(u==NULL || id[0]=='\0')
215
+                return(NULL);
216
+        for(i=0;i<u->sizeclients;i++) {
217
+                c=u->clients+i;
218
+                if(strcmp(id,c->id)==0)
219
+                        return(c);
220
+        }
221
+        return(NULL);
222
+}
223
+
224
+int
225
+urusai_send(urusai *u, char *outbuf, int outbuf_used, client *destclient)
226
+{
227
+        struct sockaddr_in to;
228
+        if(u==NULL || outbuf==NULL || outbuf_used<=0 || destclient==NULL)
229
+                return(-1);
230
+        memcpy(&to,&(destclient->addr),sizeof(to));
231
+        if(sendto(u->fd,outbuf,outbuf_used,0,(struct sockaddr *)&to,sizeof(to))==-1)
232
+                return(-1);
233
+        return(0);
234
+}
235
+
236
+int
237
+msg_parse(char *inbuf, int inbuf_used,char **serial,char **origid,char **destid,char **cmd, char **contents)
238
+{
239
+        char *ptr;
240
+        if(inbuf==NULL || inbuf_used<=0)
241
+                return(-1);
242
+        *serial=inbuf;
243
+        if((ptr=memchr(*serial,0,inbuf_used-(*serial-inbuf)))==NULL)
244
+                return(-1);
245
+        *origid=ptr+1;
246
+        if((ptr=memchr(*origid,0,inbuf_used-(*origid-inbuf)))==NULL)
247
+                return(-1);
248
+        *destid=ptr+1;
249
+        if((ptr=memchr(*destid,0,inbuf_used-(*destid-inbuf)))==NULL)
250
+                return(-1);
251
+        *cmd=ptr+1;
252
+        if((ptr=memchr(*cmd,0,inbuf_used-(*cmd-inbuf)))==NULL)
253
+                return(-1);
254
+        *contents=ptr+1;
255
+        if((ptr=memchr(*contents,0,inbuf_used-(*contents-inbuf)))==NULL)
256
+                return(-1);
257
+        return(0);
258
+}
259
+
260
+int msg_compose(char *outbuf, int bufsize, char *serial, char *origid, char *destid, char *cmd, char *contents)
261
+{
262
+        int totallen,len;
263
+        char *ptr;
264
+        if(outbuf==NULL || bufsize<=0 || serial==NULL)
265
+                return(-1);
266
+        totallen=strlen(serial)+1+
267
+                ((origid==NULL)?0:strlen(origid))+1+
268
+                ((destid==NULL)?0:strlen(destid))+1+
269
+                ((cmd==NULL)?0:strlen(cmd))+1+
270
+                ((contents==NULL)?0:strlen(contents))+1;
271
+        if(totallen>bufsize || totallen>MAXPACKETSIZE)
272
+                return(-1);
273
+        ptr=outbuf;
274
+        len=strlen(serial);
275
+        memcpy(ptr,serial,len),ptr+=len;
276
+        *(ptr++)=0;
277
+        len=(origid==NULL)?0:strlen(origid);
278
+        memcpy(ptr,origid,len),ptr+=len;
279
+        *(ptr++)=0;
280
+        len=(destid==NULL)?0:strlen(destid);
281
+        memcpy(ptr,destid,len),ptr+=len;
282
+        *(ptr++)=0;
283
+        len=(cmd==NULL)?0:strlen(cmd);
284
+        memcpy(ptr,cmd,len),ptr+=len;
285
+        *(ptr++)=0;
286
+        len=(contents==NULL)?0:strlen(contents);
287
+        memcpy(ptr,contents,len),ptr+=len;
288
+        *(ptr++)=0;
289
+        return(ptr-outbuf);
290
+}
291
+