static void account_au_fn(const char *token, char *value, void *setting, FILE *f) { struct s_auth *account = setting; if (value) { // set default values for usage during runtime from Webif account->autoau = 0; if (!account->aureader_list) account->aureader_list = ll_create("aureader_list"); if (streq(value, "1")) account->autoau = 1; strtolower(value); ll_clear(account->aureader_list); LL_ITER itr = ll_iter_create(configured_readers); struct s_reader *rdr; char *pch, *saveptr1 = NULL; for (pch = strtok_r(value, ",", &saveptr1); pch != NULL; pch = strtok_r(NULL, ",", &saveptr1)) { ll_iter_reset(&itr); while ((rdr = ll_iter_next(&itr))) { if (streq(rdr->label, pch) || account->autoau) { ll_append(account->aureader_list, rdr); } } } return; } if (account->autoau == 1) { fprintf_conf(f, token, "%d\n", account->autoau); } else if (account->aureader_list) { value = mk_t_aureader(account); if (strlen(value) > 0) fprintf_conf(f, token, "%s\n", value); free_mk_t(value); } else if (cfg.http_full_cfg) { fprintf_conf(f, token, "%s\n", ""); } }
static statement *parse_func_call(linked_list *tokens) { linked_list *accumulator = ll_new(); linked_iter iterator = ll_iter_head(tokens); statement *call = new(call); call->type = FUNC_CALL; call->data = ((parse_token*)ll_iter_next(&iterator))->data; call->children = ll_new(); int paren_level = 0; ll_iter_next(&iterator); //Discard opening parenthesis for(parse_token *current = ll_iter_next(&iterator); ll_iter_has_next(&iterator); current = ll_iter_next(&iterator)) { if(paren_level == 0 && (equals_string(current->data, ",") || equals_string(current->data, ")"))) { statement *parameter = parse_simple_expression(accumulator); if(parameter != NULL) ll_add_last(call->children, parameter); ll_clear(accumulator); } else { ll_add_last(accumulator, current); } if(equals_string(current->data, "(")) paren_level += 1; else if(equals_string(current->data, ")")) paren_level -= 1; } statement *parameter = parse_simple_expression(accumulator); if(parameter != NULL) ll_add_last(call->children, parameter); ll_destroy(accumulator); return call; }
void remove_unit(unit *u) { gsl_vector_free(u->position); gsl_vector_free(u->velocity); gsl_vector_free(u->heading); gsl_vector_free(u->side); ll_clear(u->state); free(u); }
void unit_dead(unit *un) { if(!is_unit_dead(un) || un->state == NULL) return; state *current_state = (state *) un->state->value; current_state->cleanup(un); un->state = ll_clear(un->state); }
static bool _swap_hosts(s_ghttp *context) { if(!context->fallback_id) { return false; } uchar *tmp = context->host_id; context->host_id = context->fallback_id; context->fallback_id = tmp; NULLFREE(context->session_id); ll_clear(context->ecm_q); ll_clear_data(ghttp_ignored_contexts); return true; }
void hm_clear(const struct hashmap_st* hm, v_ccp_vp_func func) { if (hm && func) { struct lnklst_st** end = &hm->array[hm->array_num]; for (struct lnklst_st** pos=hm->array; pos != end; pos++) { if (ll_is_present(*pos)) { ll_foreach(*pos, each_call_func_f_, func); ll_clear(*pos); } } } }
static int32_t ghttp_recv_int(struct s_client *client, uchar *buf, int32_t l) { int32_t n = -1; s_ghttp *context = (s_ghttp *)client->ghttp; if(!client->pfd) { ll_clear(context->ecm_q); return -1; } if(client->reader->ghttp_use_ssl) { #ifdef WITH_SSL n = SSL_read(context->ssl_handle, buf, l); #endif } else { n = recv(client->pfd, buf, l, 0); } if(n > 0) { cs_debug_mask(D_CLIENT, "%s: received %d bytes from %s", client->reader->label, n, remote_txt()); client->last = time((time_t *)0); if(n > 400) { buf[n] = '\0'; cs_debug_mask(D_CLIENT, "%s: unexpected reply size %d - %s", client->reader->label, n, buf); return -1; // assumes google error, disconnects } } if(n < 5) { cs_debug_mask(D_CLIENT, "%s: read %d bytes, disconnecting", client->reader->label, n); n = -1; } return n; }
s32 getCols(char *colName, multi_file_t *prelF, multi_file_t *lpF, nfs_fb_t *FB, s32 minFull, s32 maxRelsInFF) /*********************************************************************/ { s32 i, j, k, l, R0, R1; s32 numFulls, rIndex, numFF, tPP; s32 aOffset, spOffset; char fName[64], prelName[64], indexName[64]; FILE *fp, *ofp, *ofp2; column_t C; rel_list *RL; relation_t R; mpz_t tmp; llist_t *P, Rl; s32 *buf=NULL, bufSize, bufMax, bufIndex; s32 *buf2=NULL, bufSize2, bufMax2, bufIndex2; mpz_init(tmp); tPP = approxPi_x(FB->maxP_r) + approxPi_x(FB->maxP_a); tPP = tPP - FB->rfb_size - FB->afb_size; memset(&Rl, 0, sizeof(Rl)); printf("Max # of large primes is approximately %" PRId32 ".\n", tPP); numFulls = doRowOps3(&P, &Rl, prelF, maxRelsInFF, minFull); if (numFulls < minFull) { ll_clear(P); ll_clear(&Rl); free(P); return numFulls; } /**************************************************************/ /* Convert the full relations into column_t data. */ /* This is done in several passes. First, create the column */ /* file, with only the relations. Later, we will go through */ /* and replace the relations with their corresponding primes. */ /**************************************************************/ C.numPrimes = 0; C.QCB[0] = C.QCB[1] = 0x00000000; sprintf(indexName, "%s.index", colName); if (!(ofp = fopen(colName, "wb"))) { fprintf(stderr, "getCols() Error opening %s for write!\n", colName); exit(-1); } if (!(ofp2 = fopen(indexName, "wb"))) { fprintf(stderr, "getCols() Error opening %s for write!\n", indexName); fclose(ofp); exit(-1); } /* Prep the output buffers: */ bufMax = IO_BUFFER_SIZE; if (!(buf = (s32 *)lxmalloc(bufMax*sizeof(s32),0))) { printf("getCols() : Memory allocation error for buf!\n"); exit(-1); } bufMax2 = IO_BUFFER_SIZE; if (!(buf2 = (s32 *)lxmalloc(bufMax2*sizeof(s32),0))) { printf("getCols() : Memory allocation error for buf2!\n"); exit(-1); } bufSize = bufSize2=0; /* Rl should contain just full relation-sets now. */ for (i=0,numFF=0; i<Rl.numFields; i++) { if ((Rl.index[i+1]-Rl.index[i]>0) && (P->index[i+1]==P->index[i])) { /* This is a full relation, coming from several (a,b) pairs. */ C.numRels = Rl.index[i+1] - Rl.index[i]; for (j=0; j<C.numRels; j++) { C.Rels[j] = Rl.data[Rl.index[i]+j]; #ifdef _DEBUG if ((C.Rels[j] < 0) || (C.Rels[j] > initialRelations)) { printf("Error: C.Rels[%ld] = %ld versus %ld relations!\n",j,C.Rels[j],initialRelations); exit(-1); } if (C.numRels > MAX_RELS_IN_FF) { printf("Error: relation-set %ld (i=%ld) has too many relations (%ld)!\n", numFF, i, C.numRels); exit(-1); } #endif } /* Write the column out in LF format. */ if (bufSize +2048 > bufMax) { fwrite(buf, sizeof(s32), bufSize, ofp); bufSize=0; } buf[bufSize++] = C.numRels; buf[bufSize++] = C.numPrimes; memcpy(buf+bufSize, &C.Rels, C.numRels*sizeof(s32)); bufSize += C.numRels; buf[bufSize++] = C.QCB[0]; buf[bufSize++] = C.QCB[1]; memcpy(buf+bufSize, &C.rows, C.numPrimes*sizeof(s32)); bufSize += C.numPrimes; /* And the column index info: */ if (bufSize2 + 2048 > bufMax2) { fwrite(buf2, sizeof(s32), bufSize2, ofp2); bufSize2=0; } buf2[bufSize2++] = C.numRels; memcpy(buf2+bufSize2, &C.Rels, C.numRels*sizeof(s32)); bufSize2 += C.numRels; numFF++; } } /* Flush buffers. */ fwrite(buf, sizeof(s32), bufSize, ofp); bufSize=0; fwrite(buf2, sizeof(s32), bufSize2, ofp2); bufSize2=0; fclose(ofp); fclose(ofp2); /* We won't be needing these anymore. */ ll_clear(&Rl); ll_clear(P); free(P); printf("After re-scanning files and building column indicies, numFF=%" PRId32 ".\n", numFF); bufSize = bufIndex = 0; bufSize2 = bufIndex2 = 0; /*******************************************************************************/ /* We now have a completely unprocessed column file. It has only the relations */ /* occurring in each column. We need to go through and replace each relation */ /* with the corresponding primes, QCB bits. */ /*******************************************************************************/ aOffset = FB->rfb_size; spOffset = aOffset + FB->afb_size; printf("Creating %" PRId32 " matrix columns...\n", numFF); strcpy(fName, TMP_FILE); R0=R1=0; for (i=0; i<prelF->numFiles; i++) { sprintf(prelName, "%s.%" PRId32, prelF->prefix, i); RL = getRelList(prelF, i); R1 = R0 + RL->numRels; printf("Re-read %" PRId32 " relations from %s : [%" PRId32 ", %" PRId32 ").\n", RL->numRels, prelName, R0, R1); /* Now, we have in RAM the relations numbered [R0, R1). */ if (!(fp = fopen(colName, "rb"))) { fprintf(stderr, "getCols() Error opening %s for read!\n", colName); exit(-1); } if (!(ofp = fopen(fName, "wb"))) { fprintf(stderr, "getCols() Error opening %s for write!\n", fName); fclose(fp); exit(-1); } /* Read the first block of data into the input buffer: */ bufSize2 = fread(buf2, sizeof(s32), bufMax2, fp); bufIndex2 = 0; for (j=0; j<numFF; j++) { /* Grab the next col in LF format from the input buffer. */ if ((bufIndex2 + 8192 > bufSize2) && !(feof(fp))) { memmove(buf2, buf2+bufIndex2, (bufSize2-bufIndex2)*sizeof(s32)); bufSize2 -= bufIndex2; bufIndex2=0; bufSize2 += fread(buf2+bufSize2, sizeof(s32), bufMax2-bufSize2, fp); } C.numRels = buf2[bufIndex2++]; C.numPrimes = buf2[bufIndex2++]; memcpy(&C.Rels, buf2+bufIndex2, C.numRels*sizeof(s32)); bufIndex2 += C.numRels; C.QCB[0] = buf2[bufIndex2++]; C.QCB[1] = buf2[bufIndex2++]; memcpy(&C.rows, buf2+bufIndex2, C.numPrimes*sizeof(s32)); bufIndex2 += C.numPrimes; if (bufIndex2 > bufSize2) { printf("getCols(): Unknown error: data is probably corrupt!\n"); exit(-1); } for (k=0; k<C.numRels; k++) { if ((C.Rels[k]>= R0) && (C.Rels[k] < R1)) { /* We have the factorization of this relation in RAM. */ rIndex = C.Rels[k] - R0; for (l=k; l<C.numRels; l++) C.Rels[l] = C.Rels[l+1]; C.numRels -= 1; /****************************************************************/ /* This is horribly inefficient. If we get ambitious, we should */ /* replace this with code that pulls the factors directly out */ /* of the data. But for now, it'll do. */ /****************************************************************/ dataConvertToRel(&R, &RL->relData[RL->relIndex[rIndex]]); /* Note: These '%2's cannot be `&0x01' b/c negative exponents can occur! */ if (C.numPrimes + R.rFSize + R.aFSize + R.spSize >= MAX_ROWS_IN_COL) { fprintf(stderr, "getCols(): MAX_ROWS_IN_COL exceeded!\n"); exit(-1); } for (l=0; l<R.rFSize; l++) if (R.rExps[l]%2) { C.rows[C.numPrimes] = R.rFactors[l]; C.numPrimes += 1; } for (l=0; l<R.aFSize; l++) if (R.aExps[l]%2) { C.rows[C.numPrimes] = aOffset+ R.aFactors[l]; C.numPrimes += 1; } for (l=0; l<R.spSize; l++) if (R.spExps[l]%2) { C.rows[C.numPrimes] = spOffset+ R.spFactors[l]; C.numPrimes += 1; } C.QCB[0] ^= R.qcbBits[0]; C.QCB[1] ^= R.qcbBits[1]; C.numPrimes = removeEvens(C.rows, C.numPrimes); k--; /* Since we removed this relation and shifted everything down, we need this so that after the increment, we look at the same position (which will be the next relation index, if there is another.) */ } #ifdef _DEBUG else if ((C.Rels[k] < 0) || (C.Rels[k] > initialRelations)) { printf("Error: intermediate col file is corrupt!\n"); printf("For relation-set %ld:\n", j); printf("C.numRels = %ld\n", C.numRels); printf("C.Rels[%ld] = %ld\n", k, C.Rels[k]); exit(-1); } #endif } /* Write out the column in LF format. */ if (bufSize + 2048 > bufMax) { fwrite(buf, sizeof(s32), bufSize, ofp); bufSize = 0; } buf[bufSize++] = C.numRels; buf[bufSize++] = C.numPrimes; memcpy(buf+bufSize, &C.Rels, C.numRels*sizeof(s32)); bufSize += C.numRels; buf[bufSize++] = C.QCB[0]; buf[bufSize++] = C.QCB[1]; memcpy(buf+bufSize, &C.rows, C.numPrimes*sizeof(s32)); bufSize += C.numPrimes; } R0 += RL->numRels; /* Flush the output buffer. */ fwrite(buf, sizeof(s32), bufSize, ofp); bufSize=0; fclose(fp); fclose(ofp); remove(colName); rename(fName, colName); clearRelList(RL); free(RL); } /* Finally, go back through and clean up the column file - now that none */ /* of the entries have any un-resolved relations left, all we need is */ /* the prime-indexing fields. */ if (!(fp = fopen(colName, "rb"))) { fprintf(stderr, "getCols() Error opening %s for read!\n", colName); exit(-1); } strcpy(fName, TMP_FILE); if (!(ofp = fopen(fName, "wb"))) { fprintf(stderr, "getCols() Error opening %s for write!\n", TMP_FILE); fclose(fp); exit(-1); } bufSize=0; bufSize2=bufIndex2=0; fwrite(&numFF, sizeof(s32), 1, ofp); /* Read the first block. */ bufSize2 = fread(buf2, sizeof(s32), bufMax2, fp); for (j=0; j<numFF; j++) { /* Grab the next col in LF format from the input buffer. */ if ((bufIndex2 + 1024 > bufSize2) && !(feof(fp))) { memmove(buf2, buf2+bufIndex2, (bufSize2-bufIndex2)*sizeof(s32)); bufSize2 -= bufIndex2; bufIndex2=0; bufSize2 += fread(buf2+bufSize2, sizeof(s32), bufMax2-bufSize2, fp); } C.numRels = buf2[bufIndex2++]; C.numPrimes = buf2[bufIndex2++]; memcpy(&C.Rels, buf2+bufIndex2, C.numRels*sizeof(s32)); bufIndex2 += C.numRels; C.QCB[0] = buf2[bufIndex2++]; C.QCB[1] = buf2[bufIndex2++]; memcpy(&C.rows, buf2+bufIndex2, C.numPrimes*sizeof(s32)); bufIndex2 += C.numPrimes; if (bufIndex2 > bufSize2) { printf("getCols(): Unknown error: data is probably corrupt!\n"); exit(-1); } if (C.numRels > 0) { printf("Error: relation-set %" PRId32 " still has %" PRId32 " unconverted relations!\n", j,C.numRels); printf("They are: "); for (i=0; i<C.numRels; i++) printf("%" PRId32 " ", C.Rels[i]); printf("\n"); exit(-1); } /* Write the column in SF format to the output buffer. */ buf[bufSize++] = C.numPrimes; buf[bufSize++] = C.QCB[0]; buf[bufSize++] = C.QCB[1]; memcpy(buf+bufSize, &C.rows, C.numPrimes*sizeof(s32)); bufSize += C.numPrimes; if (bufSize + 1024 > bufMax) { fwrite(buf, sizeof(s32), bufSize, ofp); bufSize=0; } } fwrite(buf, sizeof(s32), bufSize, ofp); fclose(fp); fclose(ofp); remove(colName); rename(fName, colName); free(buf); free(buf2); mpz_clear(tmp); return numFF; }
static var_t * exp_eval_function_simple(char *name, acl_function_t *af, ll_t *args) { ll_t garbage; ll_entry_t *pos; void **argv = NULL; var_t *v = NULL; int argc; int size; int i; var_t *arg; /* * Initialize garbage */ ll_init(&garbage); /* * Check argc */ argc = args->ll_size; if (argc != af->af_argc) { log_error("exp_eval_function_simple: function \"%s\" requires " "%d arguments", name, af->af_argc); return NULL; } size = (argc + 1) * sizeof (void *); argv = (void **) malloc(size); if (argv == NULL) { log_sys_error("exp_eval_function_simple: malloc"); return NULL; } memset(argv, 0, size); /* * Prepare argv */ pos = LL_START(args); for (i = 0; (arg = ll_next(args, &pos)); ++i) { if (af->af_types[i] == arg->v_type) { argv[i] = arg->v_data; continue; } /* * Type casting required. Don't care about the remains of arg * (freed with args!). */ arg = var_cast_copy(af->af_types[i], arg); if (arg == NULL) { log_error("exp_eval_function_simple: var_cast_copy " "failed"); goto error; } /* * Need to free copy later */ if (LL_INSERT(&garbage, arg) == -1) { log_error("exp_eval_function_simlpe: LL_INSERT " "failed"); var_delete(arg); goto error; } argv[i] = arg->v_data; } v = af->af_callback.fc_simple(argc, argv); error: ll_clear(&garbage, (ll_delete_t) var_delete); if (argv) { free(argv); } return v; }
static int on_OK_read_chunk(const struct jbxm_initconf_st* iconf, struct jbxm_callback_if_st* cbif) { assert(iconf); assert(cbif); assert(cbif->type == JBXM_CBT_OK_RCHUNK); assert(cbif->io_area->avail > 0); int syserr = -1; bool success = false; struct varmem_st* vm = NULL; unsigned char* buff = NULL; struct type2cb_st t2cb = { 0 }; syserr = type2bcb_(iconf, JBXM_CBT_OK_RBINARY, &t2cb); assert(syserr == 0); if (! t2cb.func) { // on_OK_read_binary() が設定されていないので終了 success = true; goto EXIT_LABEL; } #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wbad-function-cast" size_t reqsiz = (size_t)dbGET(cbif, ".libjbx-readreq-size"); #pragma GCC diagnostic pop assert(reqsiz); struct libjbxm_rdata_st* rd = dbGET(cbif, ".libjbxm-readdata"); assert(rd); // vm = calloc(1, sizeof(struct varmem_st)); if (! vm) { goto EXIT_LABEL; } vm->bytes = cbif->io_area->buff; cbif->io_area->buff = NULL; // move memory vm->bytes_len = (size_t)cbif->io_area->avail; // void* ok = ll_add_tail(rd->chunks, vm); if (! ok) { goto EXIT_LABEL; } vm = NULL; // move memory rd->chunks_sumlen += (size_t)cbif->io_area->avail; // assert(rd->chunks_sumlen <= reqsiz); if (rd->chunks_sumlen < reqsiz) { success = true; goto EXIT_LABEL; } // chunks を結合 assert(rd->chunks_sumlen == reqsiz); buff = malloc(reqsiz + 1); if (! buff) { goto EXIT_LABEL; } unsigned char* pos = buff; ll_foreach(rd->chunks, varmem_concat_, &pos); *(buff + reqsiz) = '\0'; // chunks をクリア ll_clear(rd->chunks); rd->chunks_sumlen = 0; // type, io_area の内容を変更する必要があるのでコピーして一部置き換え struct jbxm_io_area_st io_area = { .buff=buff, .bufsiz=reqsiz, .ok=true, .avail=(ssize_t)reqsiz, }; buff = NULL; // move memory struct jbxm_callback_if_st tmp_cbif = *cbif; tmp_cbif.type = t2cb.type; tmp_cbif.io_area = &io_area; syserr = t2cb.func(iconf, &tmp_cbif); free(io_area.buff); if (syserr) { goto EXIT_LABEL; } // 次回の on_pre_read_binary() で要求サイズを再設定させるためにクリア dbUNSET0(cbif, ".libjbx-readreq-size"); success = true; EXIT_LABEL: free(buff); if (! success) { free_varmem(vm); return -1; } return 0; } static int on_pre_write_chunk(const struct jbxm_initconf_st* iconf, struct jbxm_callback_if_st* cbif) { struct type2cb_st t2cb = { 0 }; int syserr = type2bcb_(iconf, JBXM_CBT_PRE_WBINARY, &t2cb); assert(syserr == 0); return libjbxm_on_pre_write_chunk(iconf, cbif, &t2cb); } static int on_post_write_chunk(const struct jbxm_initconf_st* iconf, struct jbxm_callback_if_st* cbif) { struct type2cb_st t2cb = { 0 }; int syserr = type2bcb_(iconf, JBXM_CBT_POST_WBINARY, &t2cb); assert(syserr == 0); return libjbxm_on_post_write_chunk(iconf, cbif, &t2cb); } struct libjbxm_io_st binaryio = { .callbacks = { // load, unload .on_load = call_original, .on_unload = call_original, // listener .on_accepted = libjbxm_on_accepted, .on_error = call_original, .on_disconnect = libjbxm_on_disconnect, // chunk .on_pre_read_chunk = on_pre_read_chunk, .on_OK_read_chunk = on_OK_read_chunk, .on_EOD_read_chunk = call_original, .on_post_read_chunk = call_original, .on_pre_write_chunk = on_pre_write_chunk, .on_OK_write_chunk = call_original, .on_EOD_write_chunk = call_original, .on_post_write_chunk = on_post_write_chunk, }, };
int32_t ghttp_client_init(struct s_client *cl) { int32_t handle; char *str = NULL; if(cl->reader->r_port == 0) { cl->reader->r_port = cl->reader->ghttp_use_ssl ? 443 : 80; } str = strstr(cl->reader->device, "."); if(!str) { char host[128]; cs_strncpy(host, cl->reader->device, sizeof(cl->reader->device)); snprintf(cl->reader->device, sizeof(cl->reader->device), "%s.appspot.com", host); } cs_log("%s: init google cache client %s:%d (fd=%d)", cl->reader->label, cl->reader->device, cl->reader->r_port, cl->udp_fd); if(cl->udp_fd) { network_tcp_connection_close(cl->reader, "re-init"); } handle = network_tcp_connection_open(cl->reader); if(handle < 0) { return -1; } cl->reader->tcp_connected = 2; cl->reader->card_status = CARD_INSERTED; cl->reader->last_g = cl->reader->last_s = time((time_t *)0); cl->pfd = cl->udp_fd; if(!cl->ghttp) { if(!cs_malloc(&(cl->ghttp), sizeof(s_ghttp))) { return -1; } memset(cl->ghttp, 0, sizeof(s_ghttp)); ((s_ghttp *)cl->ghttp)->post_contexts = ll_create("post contexts"); ((s_ghttp *)cl->ghttp)->ecm_q = ll_create("ecm queue"); } else { ll_clear(((s_ghttp *)cl->ghttp)->ecm_q); } if(cl->reader->ghttp_use_ssl) { #ifndef WITH_SSL cs_log("%s: use_ssl set but no ssl support available, aborting...", cl->reader->label); return -1; #endif #ifdef WITH_SSL if(ghttp_ssl_context == NULL) { return -1; } if(_ssl_connect(cl, handle)) { cl->crypted = 1; } else { network_tcp_connection_close(cl->reader, "ssl failed"); return -1; } #endif } return 0; }
static int32_t ghttp_recv_chk(struct s_client *client, uchar *dcw, int32_t *rc, uchar *buf, int32_t n) { char *data; char *hdrstr; uchar *content; int rcode, len, clen = 0; s_ghttp *context = (s_ghttp *)client->ghttp; ECM_REQUEST *er = NULL; if(n < 5) { return -1; } data = strstr((char *)buf, "HTTP/1.1 "); if(!data || ll_count(context->ecm_q) > 6) { cs_debug_mask(D_CLIENT, "%s: non http or otherwise corrupt response: %s", client->reader->label, buf); cs_ddump_mask(D_CLIENT, buf, n, "%s: ", client->reader->label); network_tcp_connection_close(client->reader, "receive error"); NULLFREE(context->session_id); ll_clear(context->ecm_q); return -1; } LL_ITER itr = ll_iter_create(context->ecm_q); er = (ECM_REQUEST *)ll_iter_next(&itr); rcode = _get_int_header(buf, "HTTP/1.1 "); clen = _get_int_header(buf, "Content-Length: "); content = (uchar *)(strstr(data, "\r\n\r\n") + 4); hdrstr = _get_header_substr(buf, "ETag: \"", "\"\r\n"); if(hdrstr) { NULLFREE(context->host_id); context->host_id = (uchar *)hdrstr; cs_debug_mask(D_CLIENT, "%s: new name: %s", client->reader->label, context->host_id); len = b64decode(context->host_id); if(len == 0 || len >= 64) { NULLFREE(context->host_id); } else { cs_debug_mask(D_CLIENT, "%s: redirected...", client->reader->label); NULLFREE(context->session_id); ll_clear_data(ghttp_ignored_contexts); ll_clear(context->ecm_q); return -1; } } hdrstr = _get_header_substr(buf, "ETag: W/\"", "\"\r\n"); if(hdrstr) { NULLFREE(context->fallback_id); context->fallback_id = (uchar *)hdrstr; cs_debug_mask(D_CLIENT, "%s: new fallback name: %s", client->reader->label, context->fallback_id); len = b64decode(context->fallback_id); if(len == 0 || len >= 64) { NULLFREE(context->fallback_id); } } hdrstr = _get_header(buf, "Set-Cookie: GSSID="); if(hdrstr) { NULLFREE(context->session_id); context->session_id = (uchar *)hdrstr; cs_debug_mask(D_CLIENT, "%s: set session_id to: %s", client->reader->label, context->session_id); } // buf[n] = '\0'; // cs_ddump_mask(D_TRACE, content, clen, "%s: reply\n%s", client->reader->label, buf); if(rcode < 200 || rcode > 204) { cs_debug_mask(D_CLIENT, "%s: http error code %d", client->reader->label, rcode); data = strstr((char *)buf, "Content-Type: application/octet-stream"); // if not octet-stream, google error. need reconnect? if(data) // we have error info string in the post content { if(clen > 0) { content[clen] = '\0'; cs_debug_mask(D_CLIENT, "%s: http error message: %s", client->reader->label, content); } } if(rcode == 503) { if(er && _is_post_context(context->post_contexts, er, false)) { if(_swap_hosts(context)) { cs_debug_mask(D_CLIENT, "%s: switching to fallback", client->reader->label); } else { cs_debug_mask(D_CLIENT, "%s: recv_chk got 503 despite post, trying reconnect", client->reader->label); network_tcp_connection_close(client->reader, "reconnect"); ll_clear(context->ecm_q); } } else { // on 503 cache timeout, retry with POST immediately (and switch to POST for subsequent) if(er) { _set_pid_status(context->post_contexts, er->onid, er->tsid, er->srvid, 0); cs_debug_mask(D_CLIENT, "%s: recv_chk got 503, trying direct post", client->reader->label); _ghttp_post_ecmdata(client, er); } } } else if(rcode == 401) { NULLFREE(context->session_id); if(er) { cs_debug_mask(D_CLIENT, "%s: session expired, trying direct post", client->reader->label); _ghttp_post_ecmdata(client, er); } } else if(rcode == 403) { client->reader->enable = 0; network_tcp_connection_close(client->reader, "login failure"); ll_clear(context->ecm_q); cs_log("%s: invalid username/password, disabling reader.", client->reader->label); } // not sure if this is needed on failure, copied from newcamd *rc = 0; memset(dcw, 0, 16); return -1; } // successful http reply (200 ok or 204 no content) hdrstr = _get_header(buf, "Pragma: context-ignore="); if(hdrstr) { if(clen > 1) { cs_ddump_mask(D_CLIENT, content, clen, "%s: pmt ignore reply - %s (%d pids)", client->reader->label, hdrstr, clen / 2); uint32_t onid = 0, tsid = 0, sid = 0; if(sscanf(hdrstr, "%4x-%4x-%4x", &onid, &tsid, &sid) == 3) { _set_pids_status(ghttp_ignored_contexts, onid, tsid, sid, content, clen); } NULLFREE(hdrstr); return -1; } NULLFREE(hdrstr); } data = strstr((char *)buf, "Pragma: context-ignore-clear"); if(data) { cs_debug_mask(D_CLIENT, "%s: clearing local ignore list (size %d)", client->reader->label, ll_count(ghttp_ignored_contexts)); ll_clear_data(ghttp_ignored_contexts); } // switch back to cache get after rapid ecm response (arbitrary atm), only effect is a slight bw save for client if(!er || _is_post_context(context->post_contexts, er, false)) { data = strstr((char *)buf, "Pragma: cached"); if(data || (client->cwlastresptime > 0 && client->cwlastresptime < 640)) { cs_debug_mask(D_CLIENT, "%s: probably cached cw (%d ms), switching back to cache get for next req", client->reader->label, client->cwlastresptime); if(er) { _is_post_context(context->post_contexts, er, true); } } } if(clen == 16) // cw in content { memcpy(dcw, content, 16); *rc = 1; er = ll_remove_first(context->ecm_q); if(!er) { return -1; } cs_ddump_mask(D_TRACE, dcw, 16, "%s: cw recv chk for idx %d", client->reader->label, er->idx); return er->idx; } else { if(clen != 0) { cs_ddump_mask(D_CLIENT, content, clen, "%s: recv_chk fail, clen = %d", client->reader->label, clen); } } return -1; }
/** * Free a linked List, first freeing all of it's elements * * @param list the list free */ void ll_free(LINKED_LIST *list){ ll_clear(list); free(list); }
void *socket_thread(void *thread) { int server_fd = ((thread_data *) thread)->socket; struct sockaddr_storage client_addr; int client_addr_size; int client_fd; thread_id send_thread_id, receive_thread_id; int bytes_handled; char buffer[BUFFER_SIZE]; time_t current_time; size_t time_buffer_bytes; struct tm *local_time; while(true) { client_addr_size = sizeof(client_addr); lock(&accept_lock); client_fd = accept(server_fd, (struct sockaddr *) &client_addr, &client_addr_size); if(client_fd == -1) { close(client_fd); continue; } unlock(&accept_lock); ((thread_data *) thread)->socket = client_fd; start_joinable_thread(&receive_thread_id, receive_thread, thread); ll_clear(((thread_data *) thread)->message_queue); for(;;) { sleep(1); if(ll_size(((thread_data *) thread)->message_queue)) { message *sending_message = ll_get(((thread_data *) thread)->message_queue, 0); current_time = time(NULL); local_time = localtime(¤t_time); if(local_time != NULL) { time_buffer_bytes = strftime(buffer, BUFFER_SIZE, "%a, %d %b %Y %T %Z", local_time); if(time_buffer_bytes != 0) { sending_message->headers[sending_message->header_size] = (char *) malloc(strlen("Echoed-at: ") + strlen(buffer) + strlen("\r\r")); strcpy(sending_message->headers[sending_message->header_size], "Echoed-at: "); strcat(sending_message->headers[sending_message->header_size], buffer); strcat(sending_message->headers[sending_message->header_size], "\r\n"); sending_message->header_size++; } } int line_index; for(line_index = 0; line_index < sending_message->header_size; line_index++) { if(write(client_fd, sending_message->headers[line_index], strlen(sending_message->headers[line_index])) != strlen(sending_message->headers[line_index])) { syslog(LOG_INFO, "Error writing"); } free(sending_message->headers[line_index]); } write(client_fd, "\r\n", strlen("\r\n")); syslog(LOG_INFO, "Message"); for(line_index = 0; line_index < sending_message->message_size; line_index++) { if(write(client_fd, sending_message->message[line_index], strlen(sending_message->message[line_index])) != strlen(sending_message->message[line_index])) { syslog(LOG_INFO, "Error writing"); } free(sending_message->message[line_index]); } write(client_fd, "\r\n", strlen("\r\n")); free(sending_message->headers); free(sending_message->message); free(sending_message); ll_remove(((thread_data *) thread)->message_queue, 0); } if(((thread_data *) thread)->should_shutdown == 1) { break; } } ll_clear(((thread_data *) thread)->message_queue); join_thread(&receive_thread_id); close(client_fd); } return NULL; }