2005-11-14 Carl Worth <cworth@cworth.org>
[ttt] / src / ttt-client.c
1 /* ttt-client.c - client handling code for tic-tac-toe game server
2  *
3  * Copyright © 2005 Carl Worth
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation; either version 2, or (at your option)
8  * any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program; if not, write to the Free Software Foundation,
17  * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
18  *
19  * Author: Carl Worth <cworth@cworth.org>
20  */
21
22 #include "ttt-client.h"
23 #include "ttt-socket.h"
24
25 ttt_client_t *
26 ttt_client_create (ttt_server_t *server, int socket, int id)
27 {
28     ttt_client_t *client;
29
30     client = xmalloc (sizeof (ttt_client_t));
31
32     client->server = server;
33     client->socket = socket;
34
35     client->id = id;
36
37     client->buf_head = client->buf;
38     client->buf_tail = client->buf;
39
40     client->request = NULL;
41     client->request_size = 0;
42     client->request_len = 0;
43
44     return client;
45 }
46
47 void
48 ttt_client_destroy (ttt_client_t *client)
49 {
50     shutdown (client->socket, SHUT_RDWR);
51
52     free (client->request);
53
54     free (client);
55 }
56
57 static void
58 _append_to_request (ttt_client_t        *client,
59                     const char          *buf,
60                     int                  size)
61 {
62     int size_needed = client->request_len + size;
63
64     if (size_needed > client->request_size) {
65         if (client->request_size == 0) {
66             client->request_size = size_needed;
67         } else {
68             while (size_needed > client->request_size)
69                 client->request_size *= 2;
70         }
71
72         client->request = xrealloc (client->request, client->request_size);
73     }
74
75     memcpy (client->request + client->request_len,
76             buf, size);
77
78     client->request_len += size;
79 }
80
81 static ttt_status_t
82 ttt_client_read_into_request_until (ttt_client_t *client, char delimeter)
83 {
84     ttt_bool_t found_delimeter = FALSE;
85     int bytes_read;
86     char *s;
87
88     client->request_len = 0;
89
90     while (1) {
91
92         if (client->buf_tail >= client->buf_head) {
93             bytes_read = xread (client->socket,
94                                 client->buf,
95                                 TTT_CLIENT_BUF_SIZE);
96             if (bytes_read == 0)
97                 return TTT_STATUS_EOF;
98             client->buf_head = client->buf;
99             client->buf_tail = client->buf_head + bytes_read;
100         }
101
102         for (s = client->buf_head; s < client->buf_tail; s++) {
103             if (*s == delimeter) {
104                 found_delimeter = TRUE;
105                 s++;
106                 break;
107             }
108         }
109
110         _append_to_request (client,
111                             client->buf_head,
112                             s - client->buf_head);
113         client->buf_head = s;
114
115         if (found_delimeter)
116             return TTT_STATUS_SUCCESS;
117     }
118 }
119
120 char *
121 ttt_client_read_line (ttt_client_t *client)
122 {
123     ttt_status_t status;
124     static const char null_terminator = '\0';
125
126     status = ttt_client_read_into_request_until (client, '\n');
127     if (status) {
128         assert (status == TTT_STATUS_EOF);
129         return NULL;
130     }
131
132     _append_to_request (client, &null_terminator, 1);
133
134     return client->request;
135 }
136
137 void
138 ttt_client_send (ttt_client_t *client, const char *message)
139 {
140     ttt_socket_write (client->socket, message, strlen (message));
141 }
142
143