Changeset 590 for libcaca/trunk/caca
- Timestamp:
- Mar 10, 2006, 8:21:33 PM (15 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
libcaca/trunk/caca/driver_network.c
r586 r590 28 28 #include <fcntl.h> 29 29 #include <string.h> 30 #include <signal.h> 31 #include <errno.h> 30 32 31 33 #if defined(HAVE_UNISTD_H) … … 41 43 static void manage_connections(caca_t *kk); 42 44 static int send_data(caca_t *kk, int fd); 43 45 ssize_t nonblock_write(int fd, char *buf, size_t len); 44 46 45 47 struct driver_private 46 { 48 { 47 49 unsigned int width, height; 48 50 unsigned int port; … … 67 69 68 70 /* Following vars are static */ 69 static char codes[] = {0xff, 0xfb, 0x01, // WILL ECHO 71 static char codes[] = {0xff, 0xfb, 0x01, // WILL ECHO 70 72 0xff, 0xfb, 0x03, // WILL SUPPRESS GO AHEAD 71 73 0xff, 253, 31, // DO NAWS … … 95 97 } 96 98 #endif 97 99 98 100 99 101 kk->drv.p->width = 80; … … 113 115 114 116 if (setsockopt(kk->drv.p->sockfd,SOL_SOCKET,SO_REUSEADDR,&yes,sizeof(int)) == -1) { 115 perror("setsockopt ");117 perror("setsockopt SO_REUSEADDR"); 116 118 return -1; 117 119 } 118 120 119 121 kk->drv.p->my_addr.sin_family = AF_INET; 120 kk->drv.p-> my_addr.sin_port = htons(kk->drv.p->port); 122 kk->drv.p-> my_addr.sin_port = htons(kk->drv.p->port); 121 123 kk->drv.p->my_addr.sin_addr.s_addr = INADDR_ANY; 122 124 memset(&(kk->drv.p->my_addr.sin_zero), '\0', 8); … … 138 140 kk->drv.p->buffer = NULL; 139 141 142 /* Ignore SIGPIPE */ 143 signal(SIGPIPE, SIG_IGN); 144 140 145 return 0; 141 146 } … … 177 182 for(i = 0; i < kk->drv.p->client_count; i++) 178 183 { 184 if(kk->drv.p->fd_list[i] == -1) 185 continue; 186 179 187 if(send_data(kk, kk->drv.p->fd_list[i])) 180 188 kk->drv.p->fd_list[i] = -1; … … 183 191 manage_connections(kk); 184 192 } 185 193 186 194 static void network_handle_resize(caca_t *kk) 187 195 { … … 192 200 { 193 201 /* Manage new connections as this function will be called sometimes 194 * more often than display 202 * more often than display 195 203 */ 196 204 manage_connections(kk); … … 210 218 kk->drv.p->clilen = sizeof(kk->drv.p->remote_addr); 211 219 fd = accept(kk->drv.p->sockfd, (struct sockaddr *) &kk->drv.p->remote_addr, &kk->drv.p->clilen); 212 if(fd != -1) /* That's non blocking socket, -1 if no connection received */ 213 { 220 221 if(fd == -1) 222 return; 223 224 /* Non blocking socket */ 225 fcntl(fd, F_SETFL, O_NONBLOCK); 226 227 if(kk->drv.p->fd_list == NULL) 228 { 229 kk->drv.p->fd_list = malloc(sizeof(int)); 214 230 if(kk->drv.p->fd_list == NULL) 215 { 216 kk->drv.p->fd_list = malloc(sizeof(int)); 217 if(kk->drv.p->fd_list == NULL) 218 return; 219 } 220 else 221 { 222 kk->drv.p->fd_list = realloc(kk->drv.p->fd_list, (kk->drv.p->client_count+1) * sizeof(int)); 223 } 224 225 if(send_data(kk, fd) == 0) 226 { 227 kk->drv.p->fd_list[kk->drv.p->client_count] = fd; 228 kk->drv.p->client_count++; 229 } 231 return; 232 } 233 else 234 { 235 kk->drv.p->fd_list = realloc(kk->drv.p->fd_list, 236 (kk->drv.p->client_count+1) * sizeof(int)); 237 } 238 239 if(send_data(kk, fd) == 0) 240 { 241 kk->drv.p->fd_list[kk->drv.p->client_count] = fd; 242 kk->drv.p->client_count++; 230 243 } 231 244 } … … 233 246 static int send_data(caca_t *kk, int fd) 234 247 { 248 ssize_t ret; 249 235 250 /* No error, there's just nothing to send yet */ 236 251 if(!kk->drv.p->buffer) … … 245 260 codes[17] = (unsigned char) (kk->drv.p->height & 0xff00)>>8; 246 261 codes[18] = (unsigned char) kk->drv.p->height & 0xff; 247 262 248 263 /* Send basic telnet codes */ 249 if (send(fd, codes,sizeof(codes) , 0) == -1) 250 return -1; 251 264 ret = nonblock_write(fd, codes, sizeof(codes)); 265 if(ret == -1) 266 return (errno == EAGAIN) ? 0 : -1; 267 252 268 /* ANSI code for move(0,0)*/ 253 if (send(fd, "\033[1,1H", 6, 0) == -1) 254 return -1; 255 269 ret = nonblock_write(fd, "\033[1,1H", 6); 270 if(ret == -1) 271 return (errno == EAGAIN) ? 0 : -1; 272 256 273 /* Send actual data */ 257 if (send(fd, kk->drv.p->buffer, kk->drv.p->size, 0) == -1) 258 return -1; 259 260 return 0; 274 ret = nonblock_write(fd, kk->drv.p->buffer, kk->drv.p->size); 275 if(ret == -1) 276 return (errno == EAGAIN) ? 0 : -1; 277 278 return 0; 279 } 280 281 ssize_t nonblock_write(int fd, char *buf, size_t len) 282 { 283 int retries = 10; 284 size_t total = 0; 285 ssize_t ret; 286 287 while(total < len) 288 { 289 do 290 { 291 ret = write(fd, buf, len); 292 if(ret < 0 && errno == EAGAIN) 293 { 294 retries--; 295 if(retries < 0) 296 break; 297 } 298 } 299 while(ret < 0 && (errno == EINTR || errno == EAGAIN)); 300 301 if(ret < 0) 302 return ret; 303 else if(ret == 0) 304 return total; 305 306 total += len; 307 buf += len; 308 } 309 310 return total; 261 311 } 262 312
Note: See TracChangeset
for help on using the changeset viewer.