1*21c1c48aSSascha Wildner /* 2*21c1c48aSSascha Wildner * 3*21c1c48aSSascha Wildner * Copyright (c) 2004 Scott Ullrich <GeekGod@GeekGod.com> 4*21c1c48aSSascha Wildner * Portions Copyright (c) 2004 Chris Pressey <cpressey@catseye.mine.nu> 5*21c1c48aSSascha Wildner * 6*21c1c48aSSascha Wildner * Copyright (c) 2004 The DragonFly Project. 7*21c1c48aSSascha Wildner * All rights reserved. 8*21c1c48aSSascha Wildner * 9*21c1c48aSSascha Wildner * This code is derived from software contributed to The DragonFly Project 10*21c1c48aSSascha Wildner * by Scott Ullrich and Chris Pressey (see above for e-mail addresses). 11*21c1c48aSSascha Wildner * 12*21c1c48aSSascha Wildner * Redistribution and use in source and binary forms, with or without 13*21c1c48aSSascha Wildner * modification, are permitted provided that the following conditions 14*21c1c48aSSascha Wildner * are met: 15*21c1c48aSSascha Wildner * 16*21c1c48aSSascha Wildner * 1. Redistributions of source code must retain the above copyright 17*21c1c48aSSascha Wildner * notice, this list of conditions and the following disclaimer. 18*21c1c48aSSascha Wildner * 19*21c1c48aSSascha Wildner * 2. Redistributions in binary form must reproduce the above copyright 20*21c1c48aSSascha Wildner * notice, this list of conditions and the following disclaimer in 21*21c1c48aSSascha Wildner * the documentation and/or other materials provided with the 22*21c1c48aSSascha Wildner * distribution. 23*21c1c48aSSascha Wildner * 24*21c1c48aSSascha Wildner * 3. Neither the name of The DragonFly Project nor the names of its 25*21c1c48aSSascha Wildner * contributors may be used to endorse or promote products derived 26*21c1c48aSSascha Wildner * from this software without specific, prior written permission. 27*21c1c48aSSascha Wildner * 28*21c1c48aSSascha Wildner * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 29*21c1c48aSSascha Wildner * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 30*21c1c48aSSascha Wildner * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 31*21c1c48aSSascha Wildner * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 32*21c1c48aSSascha Wildner * COPYRIGHT HOLDERS, CONTRIBUTORS OR VOICES IN THE AUTHOR'S HEAD 33*21c1c48aSSascha Wildner * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY 34*21c1c48aSSascha Wildner * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT 35*21c1c48aSSascha Wildner * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR 36*21c1c48aSSascha Wildner * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 37*21c1c48aSSascha Wildner * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE 38*21c1c48aSSascha Wildner * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, 39*21c1c48aSSascha Wildner * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 40*21c1c48aSSascha Wildner * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 41*21c1c48aSSascha Wildner * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING, 42*21c1c48aSSascha Wildner * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 43*21c1c48aSSascha Wildner * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 44*21c1c48aSSascha Wildner * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 45*21c1c48aSSascha Wildner * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT 46*21c1c48aSSascha Wildner * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 47*21c1c48aSSascha Wildner * SUCH DAMAGE. 48*21c1c48aSSascha Wildner */ 49*21c1c48aSSascha Wildner 50*21c1c48aSSascha Wildner /* 51*21c1c48aSSascha Wildner * conn_tcp.c 52*21c1c48aSSascha Wildner * $Id: conn_tcp.c,v 1.16 2005/02/06 19:53:19 cpressey Exp $ 53*21c1c48aSSascha Wildner */ 54*21c1c48aSSascha Wildner 55*21c1c48aSSascha Wildner #include "system.h" 56*21c1c48aSSascha Wildner #ifdef HAS_TCP 57*21c1c48aSSascha Wildner 58*21c1c48aSSascha Wildner #include <sys/types.h> 59*21c1c48aSSascha Wildner #include <sys/stat.h> 60*21c1c48aSSascha Wildner #include <sys/time.h> 61*21c1c48aSSascha Wildner #include <sys/errno.h> 62*21c1c48aSSascha Wildner #include <sys/types.h> 63*21c1c48aSSascha Wildner #include <sys/socket.h> 64*21c1c48aSSascha Wildner #include <netinet/in.h> 65*21c1c48aSSascha Wildner #include <arpa/inet.h> 66*21c1c48aSSascha Wildner 67*21c1c48aSSascha Wildner #include <err.h> 68*21c1c48aSSascha Wildner #include <errno.h> 69*21c1c48aSSascha Wildner #include <stdarg.h> 70*21c1c48aSSascha Wildner #include <stdio.h> 71*21c1c48aSSascha Wildner #include <stdlib.h> 72*21c1c48aSSascha Wildner #include <string.h> 73*21c1c48aSSascha Wildner #include <unistd.h> 74*21c1c48aSSascha Wildner 75*21c1c48aSSascha Wildner #include <libaura/buffer.h> 76*21c1c48aSSascha Wildner 77*21c1c48aSSascha Wildner #define NEEDS_DFUI_STRUCTURE_DEFINITIONS 78*21c1c48aSSascha Wildner #include "dfui.h" 79*21c1c48aSSascha Wildner #undef NEEDS_DFUI_STRUCTURE_DEFINITIONS 80*21c1c48aSSascha Wildner #include "encoding.h" 81*21c1c48aSSascha Wildner #include "conn_tcp.h" 82*21c1c48aSSascha Wildner #include "dump.h" 83*21c1c48aSSascha Wildner 84*21c1c48aSSascha Wildner /***** BACKEND ******/ 85*21c1c48aSSascha Wildner 86*21c1c48aSSascha Wildner /** High Level **/ 87*21c1c48aSSascha Wildner 88*21c1c48aSSascha Wildner /* 89*21c1c48aSSascha Wildner * Connect to the frontend. 90*21c1c48aSSascha Wildner */ 91*21c1c48aSSascha Wildner dfui_err_t 92*21c1c48aSSascha Wildner dfui_tcp_be_start(struct dfui_connection *c) 93*21c1c48aSSascha Wildner { 94*21c1c48aSSascha Wildner struct sockaddr_in servaddr; 95*21c1c48aSSascha Wildner int server_port; 96*21c1c48aSSascha Wildner int tru = 1; 97*21c1c48aSSascha Wildner 98*21c1c48aSSascha Wildner server_port = atoi(c->rendezvous); 99*21c1c48aSSascha Wildner 100*21c1c48aSSascha Wildner /* 101*21c1c48aSSascha Wildner * Create the tcp socket 102*21c1c48aSSascha Wildner */ 103*21c1c48aSSascha Wildner errno = 0; 104*21c1c48aSSascha Wildner if ((T_TCP(c)->listen_sd = socket(AF_INET, SOCK_STREAM, 0)) == -1) 105*21c1c48aSSascha Wildner return(DFUI_FAILURE); 106*21c1c48aSSascha Wildner dfui_debug("LISTEN_SOCKET<<%d>>\n", T_TCP(c)->listen_sd); 107*21c1c48aSSascha Wildner 108*21c1c48aSSascha Wildner if (setsockopt(T_TCP(c)->listen_sd, SOL_SOCKET, SO_REUSEADDR, 109*21c1c48aSSascha Wildner &tru, sizeof(tru)) == -1) { 110*21c1c48aSSascha Wildner return(DFUI_FAILURE); 111*21c1c48aSSascha Wildner } 112*21c1c48aSSascha Wildner 113*21c1c48aSSascha Wildner bzero(&servaddr, sizeof(servaddr)); 114*21c1c48aSSascha Wildner servaddr.sin_family = AF_INET; 115*21c1c48aSSascha Wildner servaddr.sin_port = htons(server_port); 116*21c1c48aSSascha Wildner switch(inet_pton(AF_INET, "127.0.0.1", &servaddr.sin_addr)) { 117*21c1c48aSSascha Wildner case 0: 118*21c1c48aSSascha Wildner warnx("inet_pton(): address not parseable"); 119*21c1c48aSSascha Wildner return(DFUI_FAILURE); 120*21c1c48aSSascha Wildner case 1: 121*21c1c48aSSascha Wildner break; 122*21c1c48aSSascha Wildner default: 123*21c1c48aSSascha Wildner warn("inet_pton()"); 124*21c1c48aSSascha Wildner return(DFUI_FAILURE); 125*21c1c48aSSascha Wildner } 126*21c1c48aSSascha Wildner 127*21c1c48aSSascha Wildner if (bind(T_TCP(c)->listen_sd, (struct sockaddr *)&servaddr, sizeof(servaddr)) == -1) { 128*21c1c48aSSascha Wildner warn("bind()"); 129*21c1c48aSSascha Wildner return(DFUI_FAILURE); 130*21c1c48aSSascha Wildner } 131*21c1c48aSSascha Wildner dfui_debug("BOUND_ON<<%d>>\n", T_TCP(c)->listen_sd); 132*21c1c48aSSascha Wildner if (listen(T_TCP(c)->listen_sd, 0) == -1) 133*21c1c48aSSascha Wildner return(DFUI_FAILURE); 134*21c1c48aSSascha Wildner dfui_debug("LISTENING_ON<<%d>>\n", T_TCP(c)->listen_sd); 135*21c1c48aSSascha Wildner /* at this point we should be listening on the rendezvous port */ 136*21c1c48aSSascha Wildner return(DFUI_SUCCESS); 137*21c1c48aSSascha Wildner } 138*21c1c48aSSascha Wildner 139*21c1c48aSSascha Wildner /* 140*21c1c48aSSascha Wildner * Tell the frontend that we're done and disconnect from it. 141*21c1c48aSSascha Wildner */ 142*21c1c48aSSascha Wildner dfui_err_t 143*21c1c48aSSascha Wildner dfui_tcp_be_stop(struct dfui_connection *c) 144*21c1c48aSSascha Wildner { 145*21c1c48aSSascha Wildner if (dfui_tcp_be_ll_exchange(c, DFUI_BE_MSG_STOP, "")) { 146*21c1c48aSSascha Wildner close(T_TCP(c)->listen_sd); 147*21c1c48aSSascha Wildner close(T_TCP(c)->connected_sd); 148*21c1c48aSSascha Wildner fclose(T_TCP(c)->stream); 149*21c1c48aSSascha Wildner return(DFUI_SUCCESS); 150*21c1c48aSSascha Wildner } else 151*21c1c48aSSascha Wildner return(DFUI_FAILURE); 152*21c1c48aSSascha Wildner } 153*21c1c48aSSascha Wildner 154*21c1c48aSSascha Wildner /** Low Level **/ 155*21c1c48aSSascha Wildner 156*21c1c48aSSascha Wildner /* 157*21c1c48aSSascha Wildner * Exchange a message with the frontend. This involves two receive()/reply() 158*21c1c48aSSascha Wildner * cycles: one to provide our message, one to get a reply from the frontend. 159*21c1c48aSSascha Wildner * 160*21c1c48aSSascha Wildner * Note that this does not immediately send the message to the frontend - 161*21c1c48aSSascha Wildner * it can't, because we're a service and it's a client. What it does is 162*21c1c48aSSascha Wildner * keep the message handy and wait for a frontend request to come in. It 163*21c1c48aSSascha Wildner * then replies to that request with our message. 164*21c1c48aSSascha Wildner * 165*21c1c48aSSascha Wildner * The protocol looks something like the following, using the PRESENT and 166*21c1c48aSSascha Wildner * SUBMIT exchange as an example: 167*21c1c48aSSascha Wildner * 168*21c1c48aSSascha Wildner * frontend (client) | backend (service) 169*21c1c48aSSascha Wildner * ------------------+------------------ 170*21c1c48aSSascha Wildner * 171*21c1c48aSSascha Wildner * [stage 1] 172*21c1c48aSSascha Wildner * READY --> ll_receive() 173*21c1c48aSSascha Wildner * <-- PRESENT(form) ll_reply() 174*21c1c48aSSascha Wildner * 175*21c1c48aSSascha Wildner * [stage 2] 176*21c1c48aSSascha Wildner * SUBMIT(form) --> ll_receive() 177*21c1c48aSSascha Wildner * <-- READY ll_reply() 178*21c1c48aSSascha Wildner * 179*21c1c48aSSascha Wildner * Each of those exchanges is a pair of calls, on our end, to 180*21c1c48aSSascha Wildner * dfui_tcp_be_ll_receive() and dfui_npipe_be_ll_reply(). 181*21c1c48aSSascha Wildner * 182*21c1c48aSSascha Wildner * The set of messages that the client can pass us is determined by 183*21c1c48aSSascha Wildner * the conversation state: 184*21c1c48aSSascha Wildner * 185*21c1c48aSSascha Wildner * o In stage 1, only READY and ABORT are meaningful. 186*21c1c48aSSascha Wildner * o After a PRESENT, the messages SUBMIT and ABORT are meaningul 187*21c1c48aSSascha Wildner * in stage 2. 188*21c1c48aSSascha Wildner * o During a PROG_*, the messages CONTINUE, CANCEL, and ABORT 189*21c1c48aSSascha Wildner * are meaningful in stage 2. 190*21c1c48aSSascha Wildner * 191*21c1c48aSSascha Wildner * If the frontend sends us with READY in stage 2, we assume it has 192*21c1c48aSSascha Wildner * fallen out of sync, so we send the same initial reply again, going 193*21c1c48aSSascha Wildner * back to stage 1 as it were. 194*21c1c48aSSascha Wildner * 195*21c1c48aSSascha Wildner * After this call, the message is available in c->ebuf. 196*21c1c48aSSascha Wildner */ 197*21c1c48aSSascha Wildner dfui_err_t 198*21c1c48aSSascha Wildner dfui_tcp_be_ll_exchange(struct dfui_connection *c, char msgtype, const char *msg) 199*21c1c48aSSascha Wildner { 200*21c1c48aSSascha Wildner char *fmsg; 201*21c1c48aSSascha Wildner 202*21c1c48aSSascha Wildner /* 203*21c1c48aSSascha Wildner * Construct our message to send. 204*21c1c48aSSascha Wildner */ 205*21c1c48aSSascha Wildner 206*21c1c48aSSascha Wildner fmsg = malloc(strlen(msg) + 2); 207*21c1c48aSSascha Wildner fmsg[0] = msgtype; 208*21c1c48aSSascha Wildner strcpy(fmsg + 1, msg); 209*21c1c48aSSascha Wildner 210*21c1c48aSSascha Wildner /* 211*21c1c48aSSascha Wildner * Get the frontend's message. 212*21c1c48aSSascha Wildner */ 213*21c1c48aSSascha Wildner 214*21c1c48aSSascha Wildner dfui_tcp_be_ll_receive(c); 215*21c1c48aSSascha Wildner 216*21c1c48aSSascha Wildner /* 217*21c1c48aSSascha Wildner * Frontend message should have been either READY or ABORT. 218*21c1c48aSSascha Wildner * If ABORT, we get out of here pronto. 219*21c1c48aSSascha Wildner */ 220*21c1c48aSSascha Wildner 221*21c1c48aSSascha Wildner if (aura_buffer_buf(c->ebuf)[0] == DFUI_FE_MSG_ABORT) { 222*21c1c48aSSascha Wildner free(fmsg); 223*21c1c48aSSascha Wildner return(DFUI_FAILURE); 224*21c1c48aSSascha Wildner } 225*21c1c48aSSascha Wildner 226*21c1c48aSSascha Wildner /* XXX if (!READY) ??? */ 227*21c1c48aSSascha Wildner 228*21c1c48aSSascha Wildner do { 229*21c1c48aSSascha Wildner dfui_tcp_be_ll_reply(c, fmsg); 230*21c1c48aSSascha Wildner 231*21c1c48aSSascha Wildner /* 232*21c1c48aSSascha Wildner * Here, the frontend has picked up our request and is 233*21c1c48aSSascha Wildner * processing it. We have to wait for the response. 234*21c1c48aSSascha Wildner */ 235*21c1c48aSSascha Wildner 236*21c1c48aSSascha Wildner dfui_tcp_be_ll_receive(c); 237*21c1c48aSSascha Wildner 238*21c1c48aSSascha Wildner /* 239*21c1c48aSSascha Wildner * Did we get READY from this? 240*21c1c48aSSascha Wildner * If so, loop! 241*21c1c48aSSascha Wildner */ 242*21c1c48aSSascha Wildner 243*21c1c48aSSascha Wildner } while (aura_buffer_buf(c->ebuf)[0] == DFUI_FE_MSG_READY); 244*21c1c48aSSascha Wildner 245*21c1c48aSSascha Wildner fmsg[0] = DFUI_BE_MSG_READY; 246*21c1c48aSSascha Wildner fmsg[1] = '\0'; 247*21c1c48aSSascha Wildner dfui_tcp_be_ll_reply(c, fmsg); 248*21c1c48aSSascha Wildner 249*21c1c48aSSascha Wildner free(fmsg); 250*21c1c48aSSascha Wildner return(DFUI_SUCCESS); 251*21c1c48aSSascha Wildner } 252*21c1c48aSSascha Wildner 253*21c1c48aSSascha Wildner /* 254*21c1c48aSSascha Wildner * Receive a message from the frontend. 255*21c1c48aSSascha Wildner * This call is synchronous. 256*21c1c48aSSascha Wildner * After this call, the NUL-terminated message is available in 257*21c1c48aSSascha Wildner * c->ebuf. 258*21c1c48aSSascha Wildner */ 259*21c1c48aSSascha Wildner dfui_err_t 260*21c1c48aSSascha Wildner dfui_tcp_be_ll_receive(struct dfui_connection *c) 261*21c1c48aSSascha Wildner { 262*21c1c48aSSascha Wildner int length; 263*21c1c48aSSascha Wildner char *buf; 264*21c1c48aSSascha Wildner 265*21c1c48aSSascha Wildner top: 266*21c1c48aSSascha Wildner 267*21c1c48aSSascha Wildner if (!T_TCP(c)->is_connected) { 268*21c1c48aSSascha Wildner dfui_debug("NOT_CONNECTED,ACCEPTING_ON<<%d>>\n", T_TCP(c)->listen_sd); 269*21c1c48aSSascha Wildner T_TCP(c)->connected_sd = accept(T_TCP(c)->listen_sd, NULL, NULL); 270*21c1c48aSSascha Wildner dfui_debug("ACCEPTED<<%d>>\n", T_TCP(c)->connected_sd); 271*21c1c48aSSascha Wildner T_TCP(c)->stream = fdopen(T_TCP(c)->connected_sd, "r+"); 272*21c1c48aSSascha Wildner T_TCP(c)->is_connected = 1; 273*21c1c48aSSascha Wildner } else { 274*21c1c48aSSascha Wildner dfui_debug("ALREADY_CONNECTED<<>>\n"); 275*21c1c48aSSascha Wildner } 276*21c1c48aSSascha Wildner 277*21c1c48aSSascha Wildner dfui_debug("WAITING<<>>\n"); 278*21c1c48aSSascha Wildner 279*21c1c48aSSascha Wildner if (read_data(T_TCP(c)->stream, (char *)&length, sizeof(length)) == -1) { 280*21c1c48aSSascha Wildner dfui_debug("LOST_THEM<<>>\n"); 281*21c1c48aSSascha Wildner fclose(T_TCP(c)->stream); 282*21c1c48aSSascha Wildner T_TCP(c)->is_connected = 0; 283*21c1c48aSSascha Wildner goto top; 284*21c1c48aSSascha Wildner } 285*21c1c48aSSascha Wildner 286*21c1c48aSSascha Wildner buf = malloc(length + 1); 287*21c1c48aSSascha Wildner if (read_data(T_TCP(c)->stream, buf, length) == -1) { 288*21c1c48aSSascha Wildner dfui_debug("LOST_THEM<<>>\n"); 289*21c1c48aSSascha Wildner fclose(T_TCP(c)->stream); 290*21c1c48aSSascha Wildner T_TCP(c)->is_connected = 0; 291*21c1c48aSSascha Wildner goto top; 292*21c1c48aSSascha Wildner } 293*21c1c48aSSascha Wildner 294*21c1c48aSSascha Wildner aura_buffer_set(c->ebuf, buf, length); 295*21c1c48aSSascha Wildner free(buf); 296*21c1c48aSSascha Wildner 297*21c1c48aSSascha Wildner dfui_debug("RECEIVED<<%s>>\n", aura_buffer_buf(c->ebuf)); 298*21c1c48aSSascha Wildner 299*21c1c48aSSascha Wildner return(DFUI_SUCCESS); 300*21c1c48aSSascha Wildner } 301*21c1c48aSSascha Wildner 302*21c1c48aSSascha Wildner /* 303*21c1c48aSSascha Wildner * Send a NUL-terminated reply to the frontend. 304*21c1c48aSSascha Wildner */ 305*21c1c48aSSascha Wildner dfui_err_t 306*21c1c48aSSascha Wildner dfui_tcp_be_ll_reply(struct dfui_connection *c, const char *fmsg) 307*21c1c48aSSascha Wildner { 308*21c1c48aSSascha Wildner int length; 309*21c1c48aSSascha Wildner 310*21c1c48aSSascha Wildner dfui_debug("SEND<<%s>>\n", fmsg); 311*21c1c48aSSascha Wildner length = strlen(fmsg); 312*21c1c48aSSascha Wildner write_data(T_TCP(c)->stream, (char *)&length, sizeof(length)); 313*21c1c48aSSascha Wildner write_data(T_TCP(c)->stream, fmsg, length); 314*21c1c48aSSascha Wildner 315*21c1c48aSSascha Wildner return(DFUI_SUCCESS); 316*21c1c48aSSascha Wildner } 317*21c1c48aSSascha Wildner 318*21c1c48aSSascha Wildner /******** FRONTEND ********/ 319*21c1c48aSSascha Wildner 320*21c1c48aSSascha Wildner /** High Level **/ 321*21c1c48aSSascha Wildner 322*21c1c48aSSascha Wildner dfui_err_t 323*21c1c48aSSascha Wildner dfui_tcp_fe_connect(struct dfui_connection *c) 324*21c1c48aSSascha Wildner { 325*21c1c48aSSascha Wildner struct sockaddr_in servaddr; 326*21c1c48aSSascha Wildner int server_port; 327*21c1c48aSSascha Wildner int connected = 0; 328*21c1c48aSSascha Wildner 329*21c1c48aSSascha Wildner server_port = atoi(c->rendezvous); 330*21c1c48aSSascha Wildner 331*21c1c48aSSascha Wildner /* 332*21c1c48aSSascha Wildner * Create the tcp socket 333*21c1c48aSSascha Wildner */ 334*21c1c48aSSascha Wildner while (!connected) { 335*21c1c48aSSascha Wildner errno = 0; 336*21c1c48aSSascha Wildner if ((T_TCP(c)->connected_sd = socket(AF_INET, SOCK_STREAM, 0)) == -1) { 337*21c1c48aSSascha Wildner return(DFUI_FAILURE); 338*21c1c48aSSascha Wildner } 339*21c1c48aSSascha Wildner 340*21c1c48aSSascha Wildner dfui_debug("CLIENT_SOCKET<<%d>>\n", T_TCP(c)->connected_sd); 341*21c1c48aSSascha Wildner bzero(&servaddr, sizeof(servaddr)); 342*21c1c48aSSascha Wildner servaddr.sin_family = AF_INET; 343*21c1c48aSSascha Wildner servaddr.sin_port = htons(server_port); 344*21c1c48aSSascha Wildner inet_pton(AF_INET, "127.0.0.1", &servaddr.sin_addr); 345*21c1c48aSSascha Wildner 346*21c1c48aSSascha Wildner if (connect(T_TCP(c)->connected_sd, (struct sockaddr *)&servaddr, 347*21c1c48aSSascha Wildner sizeof(servaddr)) == 0) { 348*21c1c48aSSascha Wildner dfui_debug("CONNECTED<<>>\n"); 349*21c1c48aSSascha Wildner connected = 1; 350*21c1c48aSSascha Wildner } else { 351*21c1c48aSSascha Wildner dfui_debug("NO_CONNECT<<>>\n"); 352*21c1c48aSSascha Wildner close(T_TCP(c)->connected_sd); 353*21c1c48aSSascha Wildner sleep(1); 354*21c1c48aSSascha Wildner } 355*21c1c48aSSascha Wildner } 356*21c1c48aSSascha Wildner 357*21c1c48aSSascha Wildner /* at this point we should be connected */ 358*21c1c48aSSascha Wildner 359*21c1c48aSSascha Wildner T_TCP(c)->stream = fdopen(T_TCP(c)->connected_sd, "r+"); 360*21c1c48aSSascha Wildner 361*21c1c48aSSascha Wildner return(DFUI_SUCCESS); 362*21c1c48aSSascha Wildner } 363*21c1c48aSSascha Wildner 364*21c1c48aSSascha Wildner dfui_err_t 365*21c1c48aSSascha Wildner dfui_tcp_fe_disconnect(struct dfui_connection *c) 366*21c1c48aSSascha Wildner { 367*21c1c48aSSascha Wildner close(T_TCP(c)->connected_sd); 368*21c1c48aSSascha Wildner return(DFUI_SUCCESS); 369*21c1c48aSSascha Wildner } 370*21c1c48aSSascha Wildner 371*21c1c48aSSascha Wildner /** Low Level **/ 372*21c1c48aSSascha Wildner 373*21c1c48aSSascha Wildner /* 374*21c1c48aSSascha Wildner * Ask for, and subsequently receieve, a message from the backend. 375*21c1c48aSSascha Wildner * msgtype should be one of the DFUI_FE_MSG_* constants. 376*21c1c48aSSascha Wildner * This call is synchronous. 377*21c1c48aSSascha Wildner * After this call, the null-terminated, encoded message is 378*21c1c48aSSascha Wildner * available in T_TCP(c)->buf. 379*21c1c48aSSascha Wildner */ 380*21c1c48aSSascha Wildner dfui_err_t 381*21c1c48aSSascha Wildner dfui_tcp_fe_ll_request(struct dfui_connection *c, char msgtype, const char *msg) 382*21c1c48aSSascha Wildner { 383*21c1c48aSSascha Wildner char *fmsg, *buf; 384*21c1c48aSSascha Wildner int length, result; 385*21c1c48aSSascha Wildner 386*21c1c48aSSascha Wildner /* 387*21c1c48aSSascha Wildner * First, assert that the connection is open. 388*21c1c48aSSascha Wildner */ 389*21c1c48aSSascha Wildner 390*21c1c48aSSascha Wildner if (c == NULL || T_TCP(c)->connected_sd == -1) 391*21c1c48aSSascha Wildner return(DFUI_FAILURE); 392*21c1c48aSSascha Wildner 393*21c1c48aSSascha Wildner /* 394*21c1c48aSSascha Wildner * Construct a message. 395*21c1c48aSSascha Wildner */ 396*21c1c48aSSascha Wildner 397*21c1c48aSSascha Wildner fmsg = malloc(strlen(msg) + 2); 398*21c1c48aSSascha Wildner fmsg[0] = msgtype; 399*21c1c48aSSascha Wildner strcpy(fmsg + 1, msg); 400*21c1c48aSSascha Wildner dfui_debug("SEND<<%s>>\n", fmsg); 401*21c1c48aSSascha Wildner 402*21c1c48aSSascha Wildner /* 403*21c1c48aSSascha Wildner * Send a NUL-terminated message to the backend. 404*21c1c48aSSascha Wildner */ 405*21c1c48aSSascha Wildner 406*21c1c48aSSascha Wildner length = strlen(fmsg); 407*21c1c48aSSascha Wildner result = write_data(T_TCP(c)->stream, (char *)&length, sizeof(length)); 408*21c1c48aSSascha Wildner dfui_debug("result<<%d>>\n", result); 409*21c1c48aSSascha Wildner result = write_data(T_TCP(c)->stream, (char *)fmsg, length); 410*21c1c48aSSascha Wildner dfui_debug("result<<%d>>\n", result); 411*21c1c48aSSascha Wildner 412*21c1c48aSSascha Wildner /* 413*21c1c48aSSascha Wildner * Receive a reply from the backend. 414*21c1c48aSSascha Wildner * If our message was a READY, this should be a message like PRESENT. 415*21c1c48aSSascha Wildner * Otherwise it should simply be a READY. 416*21c1c48aSSascha Wildner */ 417*21c1c48aSSascha Wildner 418*21c1c48aSSascha Wildner dfui_debug("WAITING<<>>\n"); 419*21c1c48aSSascha Wildner result = read_data(T_TCP(c)->stream, (char *)&length, sizeof(length)); 420*21c1c48aSSascha Wildner dfui_debug("result<<%d>>\n", result); 421*21c1c48aSSascha Wildner buf = malloc(length + 1); 422*21c1c48aSSascha Wildner result = read_data(T_TCP(c)->stream, buf, length); 423*21c1c48aSSascha Wildner dfui_debug("result<<%d>>\n", result); 424*21c1c48aSSascha Wildner aura_buffer_set(c->ebuf, buf, length); 425*21c1c48aSSascha Wildner free(buf); 426*21c1c48aSSascha Wildner 427*21c1c48aSSascha Wildner dfui_debug("RECV<<%s>>\n", aura_buffer_buf(c->ebuf)); 428*21c1c48aSSascha Wildner 429*21c1c48aSSascha Wildner free(fmsg); 430*21c1c48aSSascha Wildner 431*21c1c48aSSascha Wildner return(DFUI_SUCCESS); 432*21c1c48aSSascha Wildner } 433*21c1c48aSSascha Wildner 434*21c1c48aSSascha Wildner int 435*21c1c48aSSascha Wildner read_data(FILE *f, char *buf, int n) 436*21c1c48aSSascha Wildner { 437*21c1c48aSSascha Wildner int bcount; /* counts bytes read */ 438*21c1c48aSSascha Wildner int br; /* bytes read this pass */ 439*21c1c48aSSascha Wildner 440*21c1c48aSSascha Wildner bcount = 0; 441*21c1c48aSSascha Wildner br = 0; 442*21c1c48aSSascha Wildner while (bcount < n) { 443*21c1c48aSSascha Wildner if ((br = fread(buf, 1, n - bcount, f)) > 0) { 444*21c1c48aSSascha Wildner dfui_debug("READ_BYTES<<%d>>\n", br); 445*21c1c48aSSascha Wildner bcount += br; 446*21c1c48aSSascha Wildner buf += br; 447*21c1c48aSSascha Wildner } else if (br <= 0) { 448*21c1c48aSSascha Wildner dfui_debug("read_data_error<<%d>>\n", br); 449*21c1c48aSSascha Wildner return(-1); 450*21c1c48aSSascha Wildner } 451*21c1c48aSSascha Wildner } 452*21c1c48aSSascha Wildner return(bcount); 453*21c1c48aSSascha Wildner } 454*21c1c48aSSascha Wildner 455*21c1c48aSSascha Wildner int 456*21c1c48aSSascha Wildner write_data(FILE *f, const char *buf, int n) 457*21c1c48aSSascha Wildner { 458*21c1c48aSSascha Wildner int bcount; /* counts bytes written */ 459*21c1c48aSSascha Wildner int bw; /* bytes written this pass */ 460*21c1c48aSSascha Wildner 461*21c1c48aSSascha Wildner bcount = 0; 462*21c1c48aSSascha Wildner bw = 0; 463*21c1c48aSSascha Wildner while (bcount < n) { 464*21c1c48aSSascha Wildner if ((bw = fwrite(buf, 1, n - bcount, f)) > 0) { 465*21c1c48aSSascha Wildner dfui_debug("WROTE_BYTES<<%d>>\n", bw); 466*21c1c48aSSascha Wildner bcount += bw; 467*21c1c48aSSascha Wildner buf += bw; 468*21c1c48aSSascha Wildner } else if (bw <= 0) { 469*21c1c48aSSascha Wildner dfui_debug("write_data_error<<%d>>\n", bw); 470*21c1c48aSSascha Wildner return(-1); 471*21c1c48aSSascha Wildner } 472*21c1c48aSSascha Wildner } 473*21c1c48aSSascha Wildner return(bcount); 474*21c1c48aSSascha Wildner } 475*21c1c48aSSascha Wildner 476*21c1c48aSSascha Wildner #endif /* HAS_TCP */ 477