💾 Archived View for gmi.noulin.net › gitRepositories › tuyau › file › netFrame.c.gmi captured on 2023-01-29 at 13:27:20. Gemini links have been rewritten to link to archived content
-=-=-=-=-=-=-
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: