Browse code

Initial server implementation without encryption and test client in tcl

Dario Rodriguez authored on 05/05/2014 12:17:18
Showing 6 changed files
1 1
new file mode 100644
... ...
@@ -0,0 +1,3 @@
1
+urusaiserver/urusaiserver
2
+urusaiserver/urusaiserver.o
3
+urusaiserver/urusaiserver.c~
0 4
new file mode 100644
... ...
@@ -0,0 +1,3 @@
1
+Urusai
2
+
3
+A simple udp notifier server and client, with an integrated messaging service using UDP. 
0 4
new file mode 100644
... ...
@@ -0,0 +1,12 @@
1
+CC=gcc
2
+CFLAGS=-Wall -g
3
+LDFLAGS=
4
+
5
+all: urusaiserver
6
+
7
+clean:
8
+	rm -f urusaiserver.o urusaiserver
9
+
10
+urusaiserver: urusaiserver.o
11
+
12
+urusaiserver.o: urusaiserver.c
0 13
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
+
0 292
new file mode 100755
... ...
@@ -0,0 +1,3 @@
1
+#!/bin/sh
2
+./urusaiclient.tcl &
3
+./urusaiclient.tcl otro 10293 htpc &
0 4
new file mode 100755
... ...
@@ -0,0 +1,118 @@
1
+#!/usr/bin/wish -f
2
+#
3
+# urusaiclient.tcl
4
+#
5
+# Partially based on
6
+#   http://wiki.tcl.tk/10968
7
+#   http://wiki.tcl.tk/16733
8
+#
9
+# Author: Dario Rodriguez dario@softhome.net
10
+#
11
+
12
+package require udp
13
+package require sha1
14
+
15
+set host "192.168.1.249"
16
+set port 20245
17
+set from htpc
18
+#set to yurie
19
+set to otro
20
+set myport 20246
21
+set curserial 1
22
+
23
+labelframe .top -text "Conversation"
24
+labelframe .bottom -text "Message"
25
+
26
+text .t -wrap word -yscrollcommand {.s set} -state disabled
27
+scrollbar .s -command {.t yview}
28
+entry .e -textvariable e
29
+
30
+grid .top -sticky nsew
31
+grid .bottom -sticky nsew
32
+grid row . 0 -weight 1
33
+grid column . 0 -weight 1
34
+pack .s .t -in .top -side right -fill both
35
+pack configure .t -expand 1
36
+pack .e -in .bottom -fill both -expand 1
37
+
38
+focus .e
39
+update
40
+bind .e <Return> {newmessage $e; set e {};break}
41
+
42
+proc appendline { from line } {
43
+        .t conf -state normal
44
+        .t insert end "$from: $line\n"
45
+        .t conf -state disabled
46
+        .t yview end
47
+}
48
+
49
+# AI
50
+proc newmessage { line } {
51
+        global from to
52
+        appendline "Me" $line
53
+        sendmessage [genserial] $from $to message $line
54
+}
55
+
56
+# Network code
57
+proc recvmessage {} {
58
+        global sock from
59
+        set data [read $sock]
60
+        binary scan $data H* hex
61
+        puts $hex
62
+        set pos 1
63
+        set num ""
64
+        set mystr ""
65
+        set elems [list]
66
+        foreach c [split $hex ""] {
67
+                set num "$num$c"
68
+                set pos [expr 1-$pos]
69
+                if { $pos == 1 } {
70
+                        if { [string compare $num "00"]==0 } {
71
+                                lappend elems $mystr
72
+                                set mystr ""
73
+                        } else {
74
+                                set mystr "$mystr[binary format H* $num]"
75
+                        }
76
+                        set num ""
77
+                }
78
+        }
79
+        set serial [lindex $elems 0]
80
+        set msgfrom [lindex $elems 1]
81
+        set msgto [lindex $elems 2]
82
+        set cmd [lindex $elems 3]
83
+        set contents [lindex $elems 4]
84
+        appendline "server" "$serial|$msgfrom|$msgto|$cmd|$contents"
85
+        if { [string compare $cmd "message"]==0 } {
86
+                sendmessage $serial $from $msgfrom "receipt" ""
87
+        }
88
+}
89
+
90
+proc sendmessage { serial from to cmd contents } {
91
+        global sock host port
92
+        set msg [format "%s\0%s\0%s\0%s\0%s\0" $serial $from $to $cmd $contents]
93
+        udp_conf $sock $host $port
94
+        puts -nonewline $sock $msg
95
+}
96
+
97
+proc genserial { } {
98
+        global curserial from to
99
+        incr curserial
100
+        return [string range [::sha1::sha1 -hex -- "[clock seconds]|[set from]|[set to]|[set curserial]"] 0 8]
101
+
102
+}
103
+
104
+
105
+if { [llength $argv]>=3 } {
106
+        set from [lindex $argv 0]
107
+        set myport [lindex $argv 1]
108
+        set to [lindex $argv 2]
109
+}
110
+
111
+wm title . "urusai/tcl - $from"
112
+set sock [udp_open]
113
+udp_conf $sock $host $myport
114
+fconfigure $sock -buffering none -translation binary
115
+fileevent $sock readable recvmessage
116
+
117
+sendmessage [genserial] $from "" ping ""
118
+