Welcome to mirror list, hosted at ThFree Co, Russian Federation.

is_seqnum_v2_sv.c « socket_tests « cygwin « winsup - cygwin.com/git/newlib-cygwin.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
blob: 3d1c37b5c88b5c7ed24ff6b718f98a0ff2290825 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
/*************************************************************************\
*                  Copyright (C) Michael Kerrisk, 2018.                   *
*                                                                         *
* This program is free software. You may use, modify, and redistribute it *
* under the terms of the GNU General Public License as published by the   *
* Free Software Foundation, either version 3 or (at your option) any      *
* later version. This program is distributed without any warranty.  See   *
* the file COPYING.gpl-v3 for details.                                    *
\*************************************************************************/

/* Solution for Exercise 59-2:b */

/* is_seqnum_v2_sv.c

   A simple Internet stream socket server. Our service is to provide unique
   sequence numbers to the client.

   This program is the same as is_seqnum_cl.c, except that it uses the functions
   in our inet_sockets.c library to simplify set up of the server's socket.

   Usage:  is_seqnum_sv [init-seq-num]  (default = 0)

   See also is_seqnum_v2_cl.c.
*/
#include "is_seqnum_v2.h"

int
main(int argc, char *argv[])
{
    uint32_t seqNum;
    char reqLenStr[INT_LEN];            /* Length of requested sequence */
    char seqNumStr[INT_LEN];            /* Start of granted sequence */
    struct sockaddr *claddr;
    int lfd, cfd, reqLen;
    socklen_t addrlen, alen;
    char addrStr[IS_ADDR_STR_LEN];

    if (argc > 1 && strcmp(argv[1], "--help") == 0)
        usageErr("%s [init-seq-num]\n", argv[0]);

    seqNum = (argc > 1) ? getInt(argv[1], 0, "init-seq-num") : 0;

    /* Ignore the SIGPIPE signal, so that we find out about broken connection
       errors via a failure from write(). */

    if (signal(SIGPIPE, SIG_IGN) == SIG_ERR)    errExit("signal");

    lfd = inetListen(PORT_NUM_STR, 5, &addrlen);
    if (lfd == -1)
        fatal("inetListen() failed");

    /* Allocate a buffer large enough to hold the client's socket address */

    claddr = malloc(addrlen);
    if (claddr == NULL)
        errExit("malloc");

    for (;;) {                  /* Handle clients iteratively */

        /* Accept a client connection, obtaining client's address */

        alen = addrlen;
        cfd = accept(lfd, (struct sockaddr *) claddr, &alen);
        if (cfd == -1) {
            errMsg("accept");
            continue;
        }

        printf("Connection from %s\n", inetAddressStr(claddr, alen,
                        addrStr, IS_ADDR_STR_LEN));

        /* Read client request, send sequence number back */

        if (readLine(cfd, reqLenStr, INT_LEN) <= 0) {
            close(cfd);
            continue;                   /* Failed read; skip request */
        }

        reqLen = atoi(reqLenStr);
        if (reqLen <= 0) {              /* Watch for misbehaving clients */
            close(cfd);
            continue;                   /* Bad request; skip it */
        }

        snprintf(seqNumStr, INT_LEN, "%d\n", seqNum);
        if (write(cfd, seqNumStr, strlen(seqNumStr)) != strlen(seqNumStr))
            fprintf(stderr, "Error on write");

        seqNum += reqLen;               /* Update sequence number */

        if (close(cfd) == -1)           /* Close connection */
            errMsg("close");
    }
}