Browse code

Display first lines of the loaded file

Dario Rodriguez authored on 18/08/2020 20:31:28
Showing 1 changed files
1 1
new file mode 100644
... ...
@@ -0,0 +1,513 @@
1
+/*
2
+ * socklib.c
3
+ *
4
+ * Handy functions for IPv4 socket connections.
5
+ *
6
+ * Author: Dario Rodriguez dario@softhome.net
7
+ * This file is licensed under the terms of the GNU LGPL v2+
8
+ */
9
+
10
+#include <stdlib.h>
11
+#include <unistd.h>
12
+#include <string.h>
13
+#include <netdb.h>
14
+#include <errno.h>
15
+#include <fcntl.h>
16
+#include <netinet/in.h>
17
+#include <netinet/tcp.h>
18
+#include <sys/types.h>
19
+#include <sys/socket.h>
20
+#include <sys/select.h>
21
+#include <sys/ioctl.h>
22
+
23
+#include "socklib.h"
24
+
25
+typedef struct _sselect {
26
+        fd_set readset;
27
+        fd_set writeset;
28
+        int maxfd;
29
+        int numfd;
30
+        fd_set readresult;
31
+        fd_set writeresult;
32
+        int sizeresult;
33
+        int readresultreturned;
34
+        int writeresultreturned;
35
+        int sizeuserptr;
36
+        void **userptr;
37
+} _sselect;
38
+
39
+
40
+#ifndef FILLTV
41
+#define FILLTV(tv,sec,usec) (tv).tv_sec=(sec),(tv).tv_usec=(usec)
42
+#endif
43
+
44
+#ifndef FILLIPV4ADDR
45
+#define FILLIPV4ADDR(a,family,addr,port) \
46
+                memset(&(a),0,sizeof(struct sockaddr_in)),\
47
+                s.sin_family=family,\
48
+                s.sin_addr.s_addr=addr,\
49
+                s.sin_port=htons(port)
50
+#endif
51
+
52
+#define USERPTRBLOCKSIZE 1024
53
+
54
+static int sselect_adduserptr(_sselect *ssel, int fd, void *userptr);
55
+static int sselect_clearuserptr(_sselect *ssel, int fd);
56
+
57
+char *
58
+ipv4_genip(char *hostname, long *resulthostsize)
59
+{
60
+        struct addrinfo hints,*ai;
61
+        struct sockaddr_in *in;
62
+        char *host;
63
+        memset(&hints,0,sizeof(hints));
64
+        hints.ai_family=AF_INET;
65
+        if(getaddrinfo(hostname,NULL,&hints,&ai)!=0)
66
+                return(NULL);
67
+        in=(struct sockaddr_in *)ai->ai_addr;
68
+        if(in->sin_family!=AF_INET) {
69
+                freeaddrinfo(ai),ai=NULL;
70
+                return(NULL);
71
+        }
72
+        *resulthostsize=4;
73
+        if(in==NULL || (host=malloc(*resulthostsize))==NULL) {
74
+                freeaddrinfo(ai),ai=NULL;
75
+                return(NULL);
76
+        }
77
+        memcpy(host,&(in->sin_addr),*resulthostsize);
78
+        freeaddrinfo(ai),ai=NULL;
79
+        return(host);
80
+}
81
+
82
+int
83
+ipv4_genport(char *portname, int fallback)
84
+{
85
+        struct addrinfo hints,*ai;
86
+        struct sockaddr_in *in;
87
+        int port;
88
+        if(*portname>='0' && *portname<='9')
89
+                return(atoi(portname));
90
+        memset(&hints,0,sizeof(hints));
91
+        hints.ai_family=AF_INET;
92
+        if(getaddrinfo(NULL,portname,&hints,&ai)!=0)
93
+                return(fallback);
94
+        if((in=((struct sockaddr_in *)ai->ai_addr))==NULL) {
95
+                freeaddrinfo(ai),ai=NULL;
96
+                return(fallback);
97
+        }
98
+	port=htons(in->sin_port);
99
+        freeaddrinfo(ai),ai=NULL;
100
+        return(port);
101
+}
102
+
103
+int
104
+ipv4_preconnect(char *host, long hostsize, int port) /* setup socket, set non-blocking, connect(2) call */
105
+{
106
+        struct sockaddr_in c,s;
107
+        int fd;
108
+        int res,err;
109
+        FILLIPV4ADDR(c,AF_INET,htonl(INADDR_ANY),0);
110
+        FILLIPV4ADDR(c,AF_INET,htonl(INADDR_ANY),port);
111
+        memcpy(&(s.sin_addr.s_addr),host,hostsize);
112
+        if((fd=socket(AF_INET,SOCK_STREAM,0 /* any protocol */))==-1)
113
+                return(-1);
114
+        if(bind(fd,(struct sockaddr *)&c,sizeof(c))!=0) {
115
+                close(fd),fd=-1;
116
+                return(-1);
117
+        }
118
+        sock_setblocking(fd,0);
119
+        res=connect(fd,(struct sockaddr *)&s,sizeof(s));
120
+        err=errno;
121
+        if(res==-1 && err!=EINPROGRESS) {
122
+                close(fd),fd=-1;
123
+                return(-1);
124
+        }
125
+        return(fd);
126
+}
127
+
128
+int
129
+ipv4_connect(int fd, long timeoutmsec) /* tests writeability */
130
+{
131
+        struct timeval tv;
132
+        fd_set wset;
133
+        FILLTV(tv,timeoutmsec/1000L,(timeoutmsec%(1000L))*1000L);
134
+        FD_ZERO(&wset);
135
+        FD_SET(fd,&wset);
136
+        if(select(fd+1,NULL,&wset,NULL,&tv)>0)
137
+                return(0);
138
+        return(-1);
139
+}
140
+
141
+int
142
+ipv4_postconnect(int fd) /* hopefully connect(2) suceeded, set blocking */
143
+{
144
+        sock_setblocking(fd,1);
145
+        return(0);
146
+}
147
+
148
+int
149
+ipv4_server(int port)
150
+{
151
+        return(ipv4_serverbinded(NULL,0,port));
152
+}
153
+
154
+int
155
+ipv4_serverbinded(char *host, long hostsize, int port)
156
+{
157
+        struct sockaddr_in s;
158
+        int fd;
159
+        if((fd=socket(AF_INET,SOCK_STREAM,0 /* any protocol */))==-1)
160
+                return(-1);
161
+        FILLIPV4ADDR(s,AF_INET,htonl(INADDR_ANY),port);
162
+        if(host!=NULL)
163
+                memcpy(&(s.sin_addr.s_addr),host,hostsize);
164
+        if(bind(fd,(struct sockaddr *)&s,sizeof(s))!=0) {
165
+                close(fd),fd=-1;
166
+                return(-1);
167
+        }
168
+        if(listen(fd,4)==-1) {
169
+                close(fd),fd=-1;
170
+                return(-1);
171
+        }
172
+        return(fd);
173
+}
174
+
175
+int
176
+sock_accept(int fd)
177
+{
178
+        int newfd;
179
+        struct sockaddr_in s;
180
+        socklen_t slen;
181
+        slen=sizeof(s);
182
+        if(fd==-1 || (newfd=accept(fd,(struct sockaddr *)&s,&slen))==-1)
183
+                return(-1);
184
+        return(newfd);
185
+}
186
+
187
+int
188
+sock_getinfo(int fd, int *iplen, char *ip, int *port) /* ip must be at least 16 bytes to have room for an ipv6 address */
189
+{
190
+        struct sockaddr c;
191
+        struct sockaddr_in *c4;
192
+        struct sockaddr_in6 *c6;
193
+        socklen_t clen;
194
+        if(fd==-1)
195
+                return(-1);
196
+        clen=sizeof(c);
197
+        if(getsockname(fd,(struct sockaddr *)&c,&clen)==-1)
198
+                return(-1);
199
+        if(c.sa_family!=AF_INET && c.sa_family!=AF_INET6)
200
+                return(-1);
201
+        if(c.sa_family==AF_INET) {
202
+                c4=(struct sockaddr_in *) &c;
203
+                *iplen=sizeof(c4->sin_addr.s_addr);
204
+                memcpy(ip,&(c4->sin_addr.s_addr),*iplen);
205
+                *port=ntohs(c4->sin_port);
206
+        } else {
207
+                c6=(struct sockaddr_in6 *) &c;
208
+                *iplen=sizeof(c6->sin6_addr);
209
+                memcpy(ip,&(c6->sin6_addr),*iplen);
210
+                *port=ntohs(c6->sin6_port);
211
+        }
212
+        return(0);
213
+}
214
+
215
+int
216
+sock_queued(int fd)
217
+{
218
+        int n;
219
+        if(ioctl(fd,FIONREAD,&n)!=0)
220
+                return(-1);
221
+        return(n);
222
+}
223
+
224
+int
225
+sock_setblocking(int fd, int block)
226
+{
227
+        int fl;
228
+        if((fl=fcntl(fd,F_GETFL,0))==-1)
229
+                return(-1);
230
+        fl=(block)?(fl&(~O_NONBLOCK)):(fl|O_NONBLOCK);
231
+        return(fcntl(fd,F_SETFL,fl));
232
+}
233
+
234
+int
235
+sock_readable(int fd) /* tests readability */
236
+{
237
+        struct timeval tv;
238
+        fd_set rset;
239
+        FILLTV(tv,0,0);
240
+        FD_ZERO(&rset);
241
+        FD_SET(fd,&rset);
242
+        if(select(fd+1,&rset,NULL,NULL,&tv)>0)
243
+                return(0);
244
+        return(-1);
245
+}
246
+
247
+sselect *
248
+sselect_init(void)
249
+{
250
+        _sselect *ssel;
251
+        if((ssel=malloc(sizeof(_sselect)))==NULL)
252
+                return(NULL);
253
+        memset(ssel,0,sizeof(_sselect));
254
+        sselect_reset((sselect *)ssel);
255
+        return((sselect *)ssel);
256
+}
257
+
258
+void
259
+sselect_free(sselect *paramssel)
260
+{
261
+        _sselect *ssel=(_sselect *)paramssel;
262
+        if(ssel==NULL)
263
+                return;
264
+        if(ssel->userptr!=NULL) {
265
+                ssel->sizeuserptr=0;
266
+                free(ssel->userptr),ssel->userptr=NULL;
267
+        }
268
+        free(ssel),ssel=NULL;
269
+}
270
+
271
+
272
+int
273
+sselect_reset(sselect *paramssel)
274
+{
275
+        _sselect *ssel=(_sselect *)paramssel;
276
+        if(ssel==NULL)
277
+                return(-1);
278
+        FD_ZERO(&(ssel->readset));
279
+        FD_ZERO(&(ssel->writeset));
280
+        ssel->maxfd=0;
281
+        ssel->numfd=0;
282
+        FD_ZERO(&(ssel->readresult));
283
+        FD_ZERO(&(ssel->writeresult));
284
+        memset(ssel->userptr,0,sizeof(void *)*ssel->sizeuserptr);
285
+        return(0);
286
+}
287
+
288
+int
289
+sselect_addread(sselect *paramssel, int fd, void *userptr)
290
+{
291
+        _sselect *ssel=(_sselect *)paramssel;
292
+        if(ssel==NULL || fd<0 || FD_ISSET(fd,&(ssel->readset)))
293
+                return(-1);
294
+        if(userptr!=NULL) {
295
+                if(sselect_adduserptr(ssel, fd, userptr)!=0)
296
+                        return(-1);
297
+        } else
298
+                sselect_clearuserptr(ssel,fd);
299
+        FD_SET(fd,&(ssel->readset));
300
+        if(fd>ssel->maxfd)
301
+                ssel->maxfd=fd;
302
+        ssel->numfd++;
303
+        return(0);
304
+}
305
+
306
+
307
+int
308
+sselect_addwrite(sselect *paramssel, int fd, void *userptr)
309
+{
310
+        _sselect *ssel=(_sselect *)paramssel;
311
+        if(ssel==NULL || fd<0 || FD_ISSET(fd,&(ssel->writeset)))
312
+                return(-1);
313
+        if(userptr!=NULL) {
314
+                if(sselect_adduserptr(ssel, fd, userptr)!=0)
315
+                        return(-1);
316
+        } else
317
+                sselect_clearuserptr(ssel,fd);
318
+        FD_SET(fd,&(ssel->writeset));
319
+        if(fd>ssel->maxfd)
320
+                ssel->maxfd=fd;
321
+        ssel->numfd++;
322
+        return(0);
323
+}
324
+
325
+int
326
+sselect_delread(sselect *paramssel, int fd)
327
+{
328
+        _sselect *ssel=(_sselect *)paramssel;
329
+        if(ssel==NULL || fd<0 || !FD_ISSET(fd,&(ssel->readset)))
330
+                return(-1);
331
+        FD_CLR(fd,&(ssel->readset));
332
+        if(fd>0 && fd==ssel->maxfd && !FD_ISSET(fd,&(ssel->writeset)))
333
+                ssel->maxfd=fd-1;
334
+        ssel->numfd--;
335
+        return(0);
336
+}
337
+
338
+
339
+int
340
+sselect_delwrite(sselect *paramssel, int fd)
341
+{
342
+        _sselect *ssel=(_sselect *)paramssel;
343
+        if(ssel==NULL || fd<0 || !FD_ISSET(fd,&(ssel->writeset)))
344
+                return(-1);
345
+        FD_CLR(fd,&(ssel->writeset));
346
+        if(fd>0 && fd==ssel->maxfd && !FD_ISSET(fd,&(ssel->readset)))
347
+                ssel->maxfd=fd-1;
348
+        ssel->numfd--;
349
+        return(0);
350
+}
351
+
352
+int
353
+sselect_wait(sselect *paramssel, int ms)
354
+{
355
+        struct timeval tv;
356
+        _sselect *ssel=(_sselect *)paramssel;
357
+        if(ssel==NULL || ms<0)
358
+                return(-1);
359
+        memcpy(&(ssel->readresult),&(ssel->readset),sizeof(fd_set));
360
+        memcpy(&(ssel->writeresult),&(ssel->writeset),sizeof(fd_set));
361
+        ssel->readresultreturned=0;
362
+        ssel->writeresultreturned=0;
363
+        FILLTV(tv,(ms/1000),(ms%1000)*1000);
364
+        if((ssel->sizeresult=select(
365
+          ssel->maxfd+1,&(ssel->readresult),
366
+          &(ssel->writeresult),NULL,&tv))<0)
367
+                return(-1);
368
+        return(ssel->sizeresult);
369
+}
370
+
371
+int
372
+sselect_getread(sselect *paramssel, int *fds, int sizefds)
373
+{
374
+        int i,n;
375
+        _sselect *ssel=(_sselect *)paramssel;
376
+        if(ssel==NULL || fds==NULL || sizefds<1)
377
+                return(-1);
378
+        for(n=0,i=ssel->readresultreturned;i<=ssel->maxfd && n<sizefds;i++) {
379
+                if(FD_ISSET(i,&(ssel->readresult))) {
380
+                        fds[n++]=i;
381
+                        FD_CLR(i,&(ssel->readresult));
382
+                }
383
+        }
384
+        ssel->readresultreturned=i;
385
+        return(n);
386
+}
387
+
388
+int
389
+sselect_getwrite(sselect *paramssel, int *fds, int sizefds)
390
+{
391
+        int i,n;
392
+        _sselect *ssel=(_sselect *)paramssel;
393
+        if(ssel==NULL || fds==NULL || sizefds<1)
394
+                return(-1);
395
+        for(n=0,i=ssel->writeresultreturned;i<=ssel->maxfd && n<sizefds;i++) {
396
+                if(FD_ISSET(i,&(ssel->writeresult))) {
397
+                        fds[n++]=i;
398
+                        FD_CLR(i,&(ssel->writeresult));
399
+                }
400
+        }
401
+        ssel->writeresultreturned=i;
402
+        return(n);
403
+}
404
+
405
+/* advanced sselect functions */
406
+int
407
+sselect_getreadfiltered(sselect *paramssel, fd_set *filter, int *fds, int sizefds)
408
+{
409
+        int i,n;
410
+        _sselect *ssel=(_sselect *)paramssel;
411
+        if(ssel==NULL || fds==NULL || sizefds<1)
412
+                return(-1);
413
+        for(n=0,i=0;i<=ssel->maxfd && n<sizefds;i++) {
414
+                if(FD_ISSET(i,&(ssel->readresult)) && FD_ISSET(i,filter)) {
415
+                        fds[n++]=i;
416
+                        FD_CLR(i,&(ssel->readresult));
417
+                }
418
+        }
419
+        return(n);
420
+}
421
+
422
+int
423
+sselect_getwritefiltered(sselect *paramssel, fd_set *filter, int *fds, int sizefds)
424
+{
425
+        int i,n;
426
+        _sselect *ssel=(_sselect *)paramssel;
427
+        if(ssel==NULL || fds==NULL || sizefds<1)
428
+                return(-1);
429
+        for(n=0,i=0;i<=ssel->maxfd && n<sizefds;i++) {
430
+                if(FD_ISSET(i,&(ssel->writeresult)) && FD_ISSET(i,filter)) {
431
+                        fds[n++]=i;
432
+                        FD_CLR(i,&(ssel->writeresult));
433
+                }
434
+        }
435
+        return(n);
436
+}
437
+
438
+void *
439
+sselect_getuserptr(sselect *paramssel, int fd)
440
+{
441
+        _sselect *ssel=(_sselect *)paramssel;
442
+        if(ssel==NULL || fd<0 || fd>=ssel->sizeuserptr)
443
+                return(NULL);
444
+        return(ssel->userptr[fd]);
445
+}
446
+
447
+
448
+/* aux functions */
449
+void
450
+sock_setfast(int fd)
451
+{
452
+        int val;
453
+        val=1;
454
+        setsockopt(fd,IPPROTO_TCP,TCP_NODELAY,(void *)&val,sizeof(val));
455
+}
456
+
457
+void
458
+sock_setunsafe(int fd)
459
+{
460
+        int val;
461
+        struct linger ltime;
462
+        val=1;
463
+        setsockopt(fd,SOL_SOCKET,SO_REUSEADDR,(void *)&val,sizeof(val));
464
+        ltime.l_onoff=1;
465
+        ltime.l_linger=0;
466
+        setsockopt(fd,SOL_SOCKET,SO_LINGER,(void *)&ltime,sizeof(ltime));
467
+}
468
+
469
+void
470
+sock_setsafe(int fd)
471
+{
472
+        int val;
473
+        struct linger ltime;
474
+        val=0;
475
+        setsockopt(fd,SOL_SOCKET,SO_REUSEADDR,(void *)&val,sizeof(val));
476
+        ltime.l_onoff=0;
477
+        ltime.l_linger=1;
478
+        setsockopt(fd,SOL_SOCKET,SO_LINGER,(void *)&ltime,sizeof(ltime));
479
+}
480
+
481
+
482
+/* local functions */
483
+static int
484
+sselect_adduserptr(_sselect *ssel, int fd, void *userptr)
485
+{
486
+        if(ssel==NULL || fd<0)
487
+                return(-1);
488
+        if(ssel->sizeuserptr<(fd+1)) {
489
+                void **newptr;
490
+                int newsize;
491
+                newsize=(fd+USERPTRBLOCKSIZE)/USERPTRBLOCKSIZE;
492
+                newsize*=USERPTRBLOCKSIZE;
493
+                if((newptr=realloc(ssel->userptr,sizeof(void *)*newsize))==NULL)
494
+                        return(-1);
495
+                ssel->userptr=newptr;
496
+                memset(ssel->userptr+ssel->sizeuserptr,0,sizeof(void *)*(newsize-ssel->sizeuserptr));
497
+                ssel->sizeuserptr=newsize;
498
+        }
499
+        ssel->userptr[fd]=userptr;
500
+        return(0);
501
+}
502
+
503
+static int
504
+sselect_clearuserptr(_sselect *ssel, int fd)
505
+{
506
+        if(ssel==NULL || fd<0)
507
+                return(-1);
508
+        if(ssel->sizeuserptr<(fd+1))
509
+                return(0);
510
+        ssel->userptr[fd]=NULL;
511
+        return(0);
512
+}
513
+