tuyau

Client/server for transfering files (like cp)
git clone https://noulin.net/git/tuyau.git
Log | Files | Refs | README

netFrame.c (6835B)


      1 
      2 
      3 /* Libsheepy documentation: https://spartatek.se/libsheepy/ */
      4 
      5 #include "netFrame.h"
      6 #include "netFrameInternal.h"
      7 
      8 #include <sys/types.h>
      9 #include <sys/socket.h>
     10 #include <errno.h>
     11 
     12 void initiateNetFrame(netFramet *self);
     13 void registerMethodsNetFrame(netFrameFunctionst *f);
     14 void initiateAllocateNetFrame(netFramet **self);
     15 void finalizeNetFrame(void);
     16 netFramet* allocNetFrame(void);
     17 local void freeNetFrame(netFramet *self);
     18 local void terminateNetFrame(netFramet **self);
     19 local char* toStringNetFrame(netFramet *self);
     20 local netFramet* duplicateNetFrame(netFramet *self);
     21 local void smashNetFrame(netFramet **self);
     22 local void finishNetFrame(netFramet **self);
     23 local const char* helpNetFrame(netFramet *self);
     24 local void setCallbackNetFrame(netFramet *self, callBackNetFramet callback, void* context);
     25 local bool sendNetFrame(netFramet *self, SSL *ssl, void* buf, size_t size);
     26 local bool receiveNetFrame(netFramet *self, SSL *ssl);
     27 local bool receiveOneNetFrame(netFramet *self, SSL *ssl);
     28 local bool endNetFrame(netFramet *self, SSL *ssl);
     29 
     30 /* enable/disable logging */
     31 /* #undef pLog */
     32 /* #define pLog(...) */
     33 
     34 bool checkLibsheepyVersionNetFrame(const char *currentLibsheepyVersion) {
     35   return eqG(currentLibsheepyVersion, LIBSHEEPY_VERSION);
     36 }
     37 
     38 void initiateNetFrame(netFramet *self) {
     39 
     40   self->type = "netFrame";
     41   if (!netFrameF) {
     42     netFrameF            = malloc(sizeof(netFrameFunctionst));
     43     registerMethodsNetFrame(netFrameF);
     44     pErrorNot0(atexit(finalizeNetFrame));
     45   }
     46   self->f = netFrameF;
     47 
     48   self->callback = null;
     49   self->context  = null;
     50 }
     51 
     52 void registerMethodsNetFrame(netFrameFunctionst *f) {
     53 
     54   f->free        = freeNetFrame;
     55   f->terminate   = terminateNetFrame;
     56   f->toString    = toStringNetFrame;
     57   f->duplicate   = duplicateNetFrame;
     58   f->smash       = smashNetFrame;
     59   f->finish      = finishNetFrame;
     60   f->help        = helpNetFrame;
     61   f->setCallback = setCallbackNetFrame;
     62   f->send        = sendNetFrame;
     63   f->receive     = receiveNetFrame;
     64   f->receiveOne  = receiveOneNetFrame;
     65   f->end         = endNetFrame;
     66 }
     67 
     68 void initiateAllocateNetFrame(netFramet **self) {
     69 
     70   if (self) {
     71     (*self) = malloc(sizeof(netFramet));
     72     if (*self) {
     73       initiateNetFrame(*self);
     74     }
     75   }
     76 }
     77 
     78 void finalizeNetFrame(void) {
     79 
     80   if (netFrameF) {
     81     freen(netFrameF);
     82   }
     83 }
     84 
     85 netFramet* allocNetFrame(void) {
     86   netFramet *r = NULL;
     87 
     88   initiateAllocateNetFrame(&r);
     89   ret r;
     90 }
     91 
     92 
     93 void cleanUpNetFrameTerminateG(netFramet **val) {
     94   terminateO(*val);
     95 }
     96 
     97 void cleanUpNetFrameFreeG(netFramet *val) {
     98   freeO(val);
     99 }
    100 
    101 void cleanUpNetFrameFinishG(netFramet *val) {
    102   finishO(val);
    103 }
    104 
    105 local void freeNetFrame(netFramet *self UNUSED) {
    106 }
    107 
    108 local void terminateNetFrame(netFramet **self) {
    109 
    110   freeNetFrame(*self);
    111   finishNetFrame(self);
    112 }
    113 
    114 
    115 local char* toStringNetFrame(netFramet *self UNUSED) {
    116 
    117   ret strdup("TODO - netFrame");
    118 }
    119 
    120 local netFramet* duplicateNetFrame(netFramet *self UNUSED) {
    121 
    122   createAllocateNetFrame(dup);
    123   ret dup;
    124 }
    125 
    126 local void smashNetFrame(netFramet **self) {
    127 
    128   finishNetFrame(self);
    129 }
    130 
    131 #if NFreeStackCheck
    132 local void finishNetFrame(netFramet **self) {
    133 
    134   register u64 rsp asm("rsp");
    135   if ((u64)*self > rsp) {
    136     logW("Probably trying to free a smallArray on stack: "BLD"%p"RST" sp: "BLD"%p"RST, *self, rsp);
    137     logBtrace;
    138   }
    139   else {
    140     freen(*self);
    141   }
    142 }
    143 #else
    144 // #if NFreeStackCheck
    145 local void finishNetFrame(netFramet **self) {
    146 
    147   freen(*self);
    148 }
    149 #endif
    150 // #if NFreeStackCheck
    151 
    152 local const char* helpNetFrame(netFramet UNUSED *self) {
    153   ret "TODO - netFrame help";
    154 }
    155 
    156 
    157 local void setCallbackNetFrame(netFramet *self, callBackNetFramet callback, void* context) {
    158   self->callback = callback;
    159   self->context  = context;
    160 }
    161 
    162 
    163 local bool sendNetFrame(netFramet *self UNUSED, SSL *ssl, void* buf, size_t size) {
    164 
    165   ssize_t status; // for netsend
    166 
    167   #define netsend(B,SZ,FLGS) procbegin\
    168     UNIQVAR(retry):\
    169     if ((status = SSL_write(ssl, B, SZ)) < 0) {\
    170       /* TODO SSL_get_error() */\
    171       shperror("Netframe send ssl error");\
    172       ret no;\
    173     }\
    174     procend
    175 
    176   if (size > 0) {
    177     netsend(&size, sizeof(size), MSG_MORE);
    178   }
    179   else {
    180     // size 0 is the last frame in this transaction
    181     netsend(&size, sizeof(size), 0);
    182     ret yes;
    183   }
    184 
    185   while(size > 0) {
    186     netsend(buf, size, 0);
    187     buf  += status;
    188     size -= status;
    189   }
    190 
    191   ret yes;
    192 }
    193 
    194 
    195 local bool receiveNetFrame(netFramet *self, SSL *ssl) {
    196   if (!self->callback) ret no;
    197 
    198   size_t size;
    199   ssize_t status; // for netrecv
    200   bool isFirstFrame = yes;
    201 
    202   #define netrecv(B, SZ, FLGS, CHECK, ENOUGH, ERROR) procbegin\
    203    UNIQVAR(retry):\
    204    if ((status = SSL_read(ssl, B, SZ)) < 0) {\
    205       /* TODO SSL_get_error() */\
    206      shperror("Netframe recv socket error");\
    207      ERROR;\
    208      ret no;\
    209    }\
    210    elif (!status) {\
    211      /* ending connection - stop receiving frames */\
    212      CHECK;\
    213    }\
    214   procend
    215 
    216   forever {
    217     netrecv(&size, sizeof(size), MSG_WAITALL, logE("ending connection");ret no,,logE("recv frame size"));
    218 
    219     if (size == 0) {
    220       /* the last frame for this transaction is received, leave this loop */
    221       if (isFirstFrame) {
    222         /* the first frame has size 0, this is a request to close the connection */
    223         logD("close socket");
    224         int sock = SSL_get_fd(ssl);
    225         close(sock);
    226       }
    227       break;
    228     }
    229 
    230     //logVarG(size);
    231 
    232     cleanCharP(buf) = malloc(size);
    233     if (!buf) ret no;
    234 
    235     void   *b  = buf;
    236     size_t  sz = size;
    237     while (sz > 0) {
    238       netrecv(b, sz, MSG_WAITALL /*flags*/, logE("ending connection: received %i, expected %i, left to receive %i", size-sz, size, sz);ret no/*frame is incomplete*/,, logE("Received: %i, left to receive: %i", size-sz ,sz));
    239       b  += status;
    240       sz -= status;
    241     }
    242 
    243     if (!self->callback(buf, size, self->context)) {
    244       // TODO error
    245     }
    246     isFirstFrame = no;
    247   }
    248 
    249   ret yes;
    250 }
    251 
    252 local bool receiveOneNetFrame(netFramet *self, SSL *ssl) {
    253   if (!self->callback) ret no;
    254 
    255   size_t size;
    256   ssize_t status; // for netrecv
    257 
    258   netrecv(&size, sizeof(size), MSG_WAITALL, logI("ending connection");ret no/*frame is incomplete*/,,logE("recv size"));
    259 
    260   //logVarG(size);
    261 
    262   if (!size) {
    263     // a frame size 0 is a request to close the connection
    264     logD("close socket");
    265     int sock = SSL_get_fd(ssl);
    266     close(sock);
    267     ret yes;
    268   }
    269 
    270   cleanCharP(buf) = malloc(size);
    271   if (!buf) ret no;
    272 
    273   void   *b  = buf;
    274   size_t  sz = size;
    275   while (sz > 0) {
    276     netrecv(b, sz, MSG_WAITALL /*flags*/, logI("ending connection");ret no/*frame is incomplete*/, logD("Received: %i, left to receive: %i", size-sz ,sz), logE("Received: %i, left to receive: %i", size-sz ,sz));
    277     b  += status;
    278     sz -= status;
    279   }
    280 
    281   if (!self->callback(buf, size, self->context)) {
    282     // TODO error
    283   }
    284   ret yes;
    285 }
    286 
    287 local bool endNetFrame(netFramet *self, SSL *ssl) {
    288   ret sendNetFrame(self, ssl, null, 0);
    289 }
    290 
    291 
    292 // vim: set expandtab ts=2 sw=2: