Example #1
0
bool build_handshake_packet(nabto_connect* con, uint8_t* buffer, size_t bufferLength, size_t* packetLength) {
    uint8_t* packetPtr;
    
    /*
     * type,   1 bytes
     * flags,  1 bytes
     * nsi cp, 4 bytes
     * nsi sp, 4 bytes
     * nsi co, 4 bytes
     * id, 20 bytes
     */
    size_t nonceLength = 38;
    uint8_t nonce[38];
    uint8_t* noncePtr = nonce;
    
    packetPtr = insert_header(buffer, con->cpnsi, con->spnsi, NP_PACKET_HDR_TYPE_GW_CONN_U, false, 0, 0, con->consi);

    //NOTE: These type and flags must match the connection attributes set
    //in the unabto_tcp_fallback_connect_thread when a connection is
    //established.
    WRITE_U8(noncePtr, NP_GW_CONN_U_TYPE_TCP); noncePtr+=1;
    WRITE_U8(noncePtr, NP_GW_CONN_U_FLAG_RELIABLE); noncePtr+=1;
    WRITE_U32(noncePtr, con->cpnsi); noncePtr+=4;
    WRITE_U32(noncePtr, con->spnsi); noncePtr+=4;
    memcpy(noncePtr, con->consi, 8); noncePtr+=8;
    memcpy(noncePtr, con->gatewayId, 20);

    packetPtr = insert_payload(packetPtr, NP_PAYLOAD_TYPE_NONCE, nonce, nonceLength);
    
    *packetLength = packetPtr - buffer;

    insert_length(buffer, *packetLength);
    return true;
}
Example #2
0
/* Insert the next line into the parser. Return 0 on success or true
   on error with errno set appropriately. */
int
rfc822parse_insert (rfc822parse_t msg, const unsigned char *line, size_t length)
{
  return (msg->in_body
          ? insert_body (msg, line, length)
          : insert_header (msg, line, length));
}
Example #3
0
void send_debug_packet_response(nabto_packet_header* header, uint32_t notification) 
{
    uint8_t* buf = nabtoCommunicationBuffer;
    uint8_t* ptr = nabtoCommunicationBuffer;
    uint8_t* end = nabtoCommunicationBuffer+nabtoCommunicationBufferSize;
    
    ptr = insert_header(ptr, header->nsi_cp, header->nsi_sp, U_DEBUG, true, header->seq, 0, NULL);
    
    if (ptr == NULL) {
        NABTO_LOG_ERROR(("Could not insert debug packet header"));
        return;
    }

    ptr = insert_notify_payload(ptr, end, NP_PAYLOAD_NOTIFY_DEBUG_OK);
    if (ptr == NULL) {
        NABTO_LOG_ERROR(("Could not insert notify payload"));
        return;
    }

    {
        uint16_t length = ptr - buf;
        insert_length(buf, length);
        send_to_basestation(buf, length, &nmc.context.gsp);
    }

}
Example #4
0
static void
set_distiller_type(DistillerBuffer *mime_headers, const char *url,
                   const char *user, C_DistillerType *dtype)
{
  const char *route = NULL;
  int route_len;
  char *disttype;

  if ((route = get_header_value(mime_headers,
                                "x-route",&route_len,NULL,NULL))
      == NULL) {

    /* Aggregator? */

    if (strncasecmp(url, fe_agg_string, strlen(fe_agg_string)) == 0) {
      /* distiller "type" is everything up to but not incl next slash */
      char disttype_tmp[256];
      int i,j;
      for (i=0, j=strlen(fe_agg_string);
           i < strlen(url) && url[j] != '/';
           i++,j++)
        ;
      strncpy(disttype_tmp, url+strlen(fe_agg_string), i);
      disttype_tmp[i] = '\0';
      SET_DISTILLER_TYPE(*dtype, disttype_tmp);

    } else {
      /* generic transformation */
      set_distiller_type_generic(mime_headers, url, user, dtype);
    }
  } else {
    
    /* pop off next element, up to a semicolon */
    char *header_value = (char *)ALLOCA(route_len+1);
    char *semicolon;

    strncpy(header_value, route, route_len);
    header_value[route_len] = '\0';
    
    if ((semicolon = strchr(header_value, ';')) != NULL) {
      int i;
      for (i=0; i<route_len && route[i] != ';'; i++)
        ;
      disttype = (char*)ALLOCA(i+2);
      strncpy(disttype, route, i);
      disttype[i] = '\0';
      insert_header(mime_headers, "x-route", semicolon+1, 0);
    } else {
      /* no semicolon, this is the last guy in the list */
      disttype = (char *)ALLOCA(route_len+2);
      strncpy(disttype, route, route_len);
      disttype[route_len] = '\0';
    }
    delete_header(mime_headers, "x-route");
    SET_DISTILLER_TYPE(*dtype, disttype);
  }
}
void send_connection_statistics(nabto_connect* con, uint8_t event) {
    size_t length;
    uint8_t* ptr = insert_header(nabtoCommunicationBuffer, 0, con->spnsi, NP_PACKET_HDR_TYPE_STATS, false, 0, 0, 0);
    uint8_t* end = nabtoCommunicationBuffer + nabtoCommunicationBufferSize;
    
    ptr = insert_stats_payload(ptr, end, event);
    if (ptr == NULL) {
        return;
    }
    ptr = insert_version_payload(ptr, end);
    if (ptr == NULL) {
        return;
    }

#if NABTO_ENABLE_CLIENT_ID
    ptr = insert_cp_id_payload(ptr, end, con);
    if (ptr == NULL) {
        return;
    }
#endif

    ptr = insert_sp_id_payload(ptr, end);
    if (ptr == NULL) {
        return;
    }

    ptr = insert_ipx_payload(ptr, end);
    if (ptr == NULL) {
        return;
    }
    ptr = insert_connect_stats_payload(ptr, end, con);
    if (ptr == NULL) {
        return;
    }

    if (!con->noRendezvous) {
        ptr = insert_rendezvous_stats_payload(ptr, end, con);
        if (ptr == NULL) {
            return;
        }
    }

    ptr = insert_connection_stats_payload(ptr, end, con);
    if (ptr == NULL) {
        return;
    }

    length = ptr - nabtoCommunicationBuffer;
    insert_length(nabtoCommunicationBuffer, length);
    send_to_basestation(nabtoCommunicationBuffer, length, &nmc.context.gsp);
}
/**
 * Build U_CONNECT response to GSP
 * @param buf                the destination buffer
 * @param seq                the sequence number
 * @param notif              the result notification
 * @param nsi                the nsi value of the connection
 * @param cpnsi              the nsi of the clientpeer to put into the packet.
 * @param spnsi              the nsi of the serverpeer to put into the packet.
 * @param isLocalConnectRsp  true if a capabilities packet 
 * @return                   the size of the response
 */
static size_t mk_gsp_connect_rsp(uint8_t* buf, uint16_t seq, uint32_t notif, uint32_t nsi, uint32_t cpnsi, uint32_t spnsi, bool isLocalConnectRsp)
{
    uint8_t* ptr = insert_header(buf, cpnsi, spnsi, U_CONNECT, true, seq, 0, 0);
    ptr = insert_payload(ptr, NP_PAYLOAD_TYPE_NOTIFY, 0, 8);
    WRITE_U32(ptr, notif); ptr += 4;
    WRITE_U32(ptr, nsi);   ptr += 4;
    
    if (isLocalConnectRsp) {
        ptr = insert_capabilities(ptr, 1 /*unenc*/);
    }

    insert_length(buf, ptr - buf);
    return ptr - buf;
}
int main(){

	int i,j,k, n,pixl, count=0;
	PIX *pixs;
	glob_t *flist;
    FILE *file=fopen("train_file.trn","w");
for(n=0;n<10;n++){
	flist=list_files(n);
    if(flist->gl_pathc==0) {
        fprintf(stderr,"No files in directory %d... Exiting...\n",n);
        exit(1);
    }



	for(i=0;i<flist->gl_pathc;i++){
		pixs=loadimage(flist->gl_pathv[i]);
		if(pixs==NULL){
            		fprintf(stderr,"Pix error... Exiting...\n");
			exit(1);
		}
 		for(j=0;j<pixGetHeight(pixs);j++){
        		for(k=0;k<pixGetWidth(pixs);k++){
            			pixGetPixel(pixs,k,j,&pixl);
            			fprintf(file,"%d",pixl); /* funny transformation of rows/columns. TODO: works with intels, but others??? */
        		}
				fprintf(file,"\n");
    		}
        count++;
		fprintf(file," %d\n",n);

	}
	globfree(flist);
	free(flist);
}
    fclose(file);
//    *file=fopen("train_file.trn","r");
    FILE *file1=fopen("train_file_header.trn","w");
    insert_header(file1,count);
    fclose(file1);
	return (0);
    
}
static void send_rendezvous_socket(nabto_socket_t socket, nabto_connect* con, uint16_t seq, nabto_endpoint* dest, nabto_endpoint *myAddress)
{
    uint8_t* ptr;
    uint8_t* buf = nabtoCommunicationBuffer;

    ptr = insert_header(buf, 0, con->spnsi, U_CONNECT, false, seq, 0, 0);
    ptr = insert_payload(ptr, NP_PAYLOAD_TYPE_EP, 0, 6);
    WRITE_U32(ptr, dest->addr); ptr += 4;
    WRITE_U16(ptr, dest->port); ptr += 2;
    if (seq > 0) {
        if (!myAddress) {
            NABTO_LOG_ERROR(("Send rendezvous called with an invalid address"));
            return;
        } else {
            ptr = insert_payload(ptr, NP_PAYLOAD_TYPE_EP, 0, 6);
            WRITE_U32(ptr, myAddress->addr); ptr += 4;
            WRITE_U16(ptr, myAddress->port); ptr += 2;
        }
    }
    {
        size_t len = ptr - buf;

        insert_length(buf, len);

        if (seq) {
            NABTO_LOG_DEBUG((PRInsi " RENDEZVOUS Send to " PRIep ": seq=%" PRIu16 "  " PRIep, MAKE_NSI_PRINTABLE(0, con->spnsi, 0), MAKE_EP_PRINTABLE(*dest), seq, MAKE_EP_PRINTABLE(*myAddress)));
        } else {
            NABTO_LOG_DEBUG((PRInsi " RENDEZVOUS Send to " PRIep ": seq=0", MAKE_NSI_PRINTABLE(0, con->spnsi, 0), MAKE_EP_PRINTABLE(*dest)));
        }
        if (dest->addr != 0 && dest->port != 0) {
            nabto_write(socket, buf, len, dest->addr, dest->port);
        } else {
            NABTO_LOG_TRACE(("invalid rendezvous packet thrown away"));
        }
    }
}
void send_connection_ended_statistics(nabto_connect* con) {
    size_t length;
    uint8_t* ptr = insert_header(nabtoCommunicationBuffer, 0, con->spnsi, NP_PACKET_HDR_TYPE_STATS, false, 0, 0, 0);
    uint8_t* end = nabtoCommunicationBuffer + nabtoCommunicationBufferSize;

    ptr = insert_stats_payload(ptr, end, NP_PAYLOAD_STATS_TYPE_UNABTO_CONNECTION_ENDED);
    if (ptr == NULL) {
        return;
    }

    ptr = insert_version_payload(ptr, end);
    if (ptr == NULL) {
        return;
    }

#if NABTO_ENABLE_CLIENT_ID
    ptr = insert_cp_id_payload(ptr, end, con);
    if (ptr == NULL) {
        return;
    }
#endif

    ptr = insert_sp_id_payload(ptr, end);
    if (ptr == NULL) {
        return;
    }
    ptr = insert_connection_stats_payload(ptr, end, con);
    if (ptr == NULL) {
        return;
    }

    length = ptr - nabtoCommunicationBuffer;
    insert_length(nabtoCommunicationBuffer, length);
    
    send_to_basestation(nabtoCommunicationBuffer, length, &nmc.context.gsp);
}
Example #10
0
File: trle.c Project: antrik/libggi
int
GGI_vnc_trle(ggi_vnc_client *client, ggi_rect *update)
{
	struct trle_ctx_t *ctx = client->trle_ctx;
	struct ggi_visual *cvis;
	const ggi_directbuffer *db;
	ggi_graphtype gt;
	int bpp;
	int cbpp;
	int count;
	unsigned char *buf;
	unsigned char *header;
	int xtiles, ytiles;
	unsigned char *work;
	int lower = 1;
	int tile_param;
	tile_func *tile;
	int xt, yt;
	int xs, ys;
	int xs_last, ys_last;
	int stride;
	ggi_rect vupdate;
	int d_frame_num;

	DPRINT("trle update %dx%d - %dx%d\n",
		update->tl.x, update->tl.y,
		update->br.x, update->br.y);

	cvis = GGI_vnc_encode_init(client, update, &vupdate, &d_frame_num);

	gt = LIBGGI_GT(cvis);

	bpp = GT_ByPP(gt);
	if (bpp == 4) {
		ggi_pixel mask =
			LIBGGI_PIXFMT(cvis)->red_mask |
			LIBGGI_PIXFMT(cvis)->green_mask |
			LIBGGI_PIXFMT(cvis)->blue_mask;
		if (!(mask & 0xff000000))
			cbpp = 3;
		else if (!(mask & 0xff)) {
			lower = 0;
			cbpp = 3;
		}
		else
			cbpp = 4;
	}
	else
		cbpp = bpp;
	count = ggi_rect_width(&vupdate) * ggi_rect_height(&vupdate);
	xtiles = (ggi_rect_width(&vupdate) + 15) / 16;
	ytiles = (ggi_rect_height(&vupdate) + 15) / 16;
	GGI_vnc_buf_reserve(&client->wbuf, client->wbuf.size + 12
		+ xtiles * ytiles + count * cbpp);
	header = &client->wbuf.buf[client->wbuf.size];
	insert_header(header, &update->tl, &vupdate, 15); /* trle */

	client->wbuf.size += 12;
	work = &client->wbuf.buf[client->wbuf.size];
	buf = work;

	db = ggiDBGetBuffer(cvis->instance.stem, d_frame_num);
	ggiResourceAcquire(db->resource, GGI_ACTYPE_READ);

	if (bpp == 1) {
		tile_param = 0;
		tile = tile_8;
	}
	else if (bpp == 2) {
		tile_param = client->reverse_endian;
		tile = tile_16;
	}
	else if (cbpp == 3 && !client->reverse_endian) {
		tile_param = lower;
		tile = tile_24;
	}
	else if (cbpp == 3) {
		tile_param = lower;
		tile = tile_rev_24;
	}
	else {
		tile_param = client->reverse_endian;
		tile = tile_32;
	}

	stride = LIBGGI_VIRTX(cvis);

	ys_last = ggi_rect_height(&vupdate) & 0xf;
	if (!ys_last)
		ys_last = 16;
	xs_last = ggi_rect_width(&vupdate) & 0xf;
	if (!xs_last)
		xs_last = 16;

	ys = 16;
	for (yt = 0; yt < ytiles; ++yt) {
		if (yt == ytiles - 1)
			ys = ys_last;
		xs = 16;
		for (xt = 0; xt < xtiles; ++xt) {
			if (xt == xtiles - 1)
				xs = xs_last;
			tile(ctx, &buf, (uint8_t *)db->read +
				((vupdate.tl.y + 16 * yt) * stride +
				 vupdate.tl.x + 16 * xt) * bpp,
				xs, ys, stride, tile_param);
		}
	}

	ggiResourceRelease(db->resource);

	client->wbuf.size += buf - work;
	return 1;
}
Example #11
0
int main(int argc, char *argv[])
{
	FILE	*pf;
	char	buff[BUFSIZE];
	int		c, i, port;
	unsigned int tsp;
	char	*scheme, *user, *host, *backup;
	pid_t 	pid;
	struct 	timespec ts;
	int 	upp;

#ifdef HAVE_GETOPT_LONG
	int option_index = 0;
	static struct option l_opts[] = {
		{"help", 0, 0, 'X'},
		{"version", 0, 0, 'V'},
		{"filename", 1, 0, 'f'},
		{"sip-uri", 1, 0, 's'},
		{"traceroute-mode", 0, 0, 'T'},
		{"usrloc-mode", 0, 0, 'U'},
		{"invite-mode", 0, 0, 'I'},
		{"message-mode", 0, 0, 'M'},
		{"contact", 1, 0, 'C'},
		{"appendix-begin", 1, 0, 'b'},
		{"appendix-end", 1, 0, 'e'},
		{"sleep", 1, 0, 'o'},
		{"expires", 1, 0, 'x'},
		{"remove-bindings", 1, 0, 'z'},
		{"flood-mode", 0, 0, 'F'},
		{"random-mode", 0, 0, 'R'},
		{"trash-chars", 1, 0, 't'},
		{"local-port", 1, 0, 'l'},
		{"remote-port", 1, 0, 'r'},
		{"outbound-proxy", 1, 0, 'p'},
		{"hostname", 1, 0, 'H'},
		{"max-fowards", 1, 0, 'm'},
		{"numeric", 0, 0, 'n'},
		{"no-via", 0, 0, 'i'},
		{"password", 1, 0, 'a'},
		{"ignore-redirects", 0, 0, 'd'},
		{"verbose", 0, 0, 'v'},
		{"extract-ip", 0, 0, 'w'},
		{"replace-string", 0, 0, 'g'},
		{"replace", 0, 0, 'G'},
		{"nagios-code", 0, 0, 'N'},
		{"nagios-warn", 1, 0, 'W'},
		{"search", 1, 0, 'q'},
		{"message-body", 1, 0, 'B'},
		{"disposition", 1, 0, 'O'},
		{"processes", 1, 0, 'P'},
		{"auth-username", 1, 0, 'u'},
		{"no-crlf", 0, 0, 'L'},
		{"timing", 1, 0, 'A'},
		{"symmetric", 0, 0, 'S'},
		{"from", 1, 0, 'c'},
		{"timeout-factor", 1, 0, 'D'},
		{"transport", 1, 0, 'E'},
		{"headers", 1, 0, 'j'},
		{0, 0, 0, 0}
	};
#endif
	/* some initialisation to be shure */
	file_b=uri_b=trace=lport=usrloc=flood=verbose=randtrash=trashchar = 0;
	warning_ext=rand_rem=nonce_count=replace_b=invite=message = 0;
	sleep_ms=empty_contact=nagios_warn=timing=outbound_proxy=symmetric = 0;
	namebeg=nameend=maxforw= -1;
	numeric=via_ins=redirects=fix_crlf=processes = 1;
	username=password=replace_str=hostname=contact_uri=mes_body = NULL;
	con_dis=auth_username=from_uri=headers = NULL;
	scheme = user = host = backup = req = rep = rec = NULL;
	re = NULL;
	address= 0;
	transport=tsp = 0;
	rport = port = 0;
	expires_t = USRLOC_EXP_DEF;
	inv_final = 64 * SIP_T1;
	memset(buff, 0, BUFSIZE);
	memset(fqdn, 0, FQDN_SIZE);

	if (argc==1) {
		print_help();
	}

	/* lots of command line switches to handle*/
#ifdef HAVE_GETOPT_LONG
	while ((c=getopt_long(argc, argv, "a:A:b:B:c:C:dD:e:E:f:Fg:GhH:iIj:l:Lm:MnNo:O:p:P:q:r:Rs:St:Tu:UvVwW:x:Xz:", l_opts, &option_index)) != EOF){
#else
	while ((c=getopt(argc, argv, "a:A:b:B:c:C:dD:e:E:f:Fg:GhH:iIj:l:Lm:MnNo:O:p:P:q:r:Rs:St:Tu:UvVwW:x:z:")) != EOF){
#endif
		switch(c){
			case 'a':
				if (strlen(optarg) == 1 && STRNCASECMP(optarg, "-", 1) == 0) {
					password = str_alloc(SIPSAK_MAX_PASSWD_LEN);
					printf("Please enter the password (max. length %i): ", SIPSAK_MAX_PASSWD_LEN);
					if (read_stdin(password, SIPSAK_MAX_PASSWD_LEN, 1) == 0) {
						exit_code(0);
					}
				}
				else {
					password=str_alloc(strlen(optarg) + 1);
					strncpy(password, optarg, strlen(optarg));
				}
				break;
			case 'A':
				timing=str_to_int(optarg);
				break;
			case 'b':
				namebeg=str_to_int(optarg);
				break;
			case 'B':
				mes_body=str_alloc(strlen(optarg) + 1);
				strncpy(mes_body, optarg, strlen(optarg));
				break;
			case 'c':
				backup=str_alloc(strlen(optarg)+1);
				strncpy(backup, optarg, strlen(optarg));
				parse_uri(backup, &scheme, &user, &host, &port);
				if (scheme  == NULL) {
					fprintf(stderr, "error: missing scheme in From URI\n");
					exit_code(2);
				}
				else if (user == NULL) {
					fprintf(stderr, "error: missing username in From URI\n");
					exit_code(2);
				}
				else if (host == NULL) {
					fprintf(stderr, "error: missing host in From URI\n");
					exit_code(2);
				}
				else {
					from_uri=str_alloc(strlen(optarg)+1);
					strncpy(from_uri, optarg, strlen(optarg));
				}
				free(backup);
				break;
			case 'C':
				if ((strlen(optarg) == 5 && STRNCASECMP(optarg, "empty", 5) == 0) || 
					(strlen(optarg) == 4 && STRNCASECMP(optarg, "none", 4) == 0)) {
					empty_contact = 1;
				}
				else if (strlen(optarg) == 1 && STRNCASECMP(optarg, "*", 1) == 0) {
					contact_uri=str_alloc(strlen(optarg)+1);
					strncpy(contact_uri, optarg, strlen(optarg));
				}
				else {
					backup=str_alloc(strlen(optarg)+1);
					strncpy(backup, optarg, strlen(optarg));
					parse_uri(backup, &scheme, &user, &host, &port);
					if (scheme == NULL) {
					    fprintf(stderr, "error: REGISTER Contact uri doesn't not contain "
						   "sip:, sips:, *, or is not empty\n");
				    	exit_code(2);
					}
					else if (user == NULL) {
						fprintf(stderr, "error: missing username in Contact uri\n");
						exit_code(2);
					}
					else if (host == NULL) {
						fprintf(stderr, "error: missing host in Contact uri\n");
						exit_code(2);
					}
					else {
						contact_uri=str_alloc(strlen(optarg)+1);
						strncpy(contact_uri, optarg, strlen(optarg));
					}
					free(backup);
				}
				break;
			case 'd':
				redirects=0;
				break;
			case 'D':
				inv_final = str_to_int(optarg) * SIP_T1;
				break;
			case 'e':
				nameend=str_to_int(optarg);
				break;
			case 'E':
				if (strlen(optarg) == 3 && 
					STRNCASECMP(optarg, "udp", 3) == 0) {
					transport = SIP_UDP_TRANSPORT;
				}
				else if (strlen(optarg) == 3 &&
						STRNCASECMP(optarg, "tcp", 3) == 0) {
					transport = SIP_TCP_TRANSPORT;
				}
				else if (strlen(optarg) == 3 &&
						STRNCASECMP(optarg, "tls", 3) == 0) {
					fprintf(stderr, "error: TLS is not supported yet, supported values: udp, tcp\n");
					exit_code(2);
					transport = SIP_TLS_TRANSPORT;
				}
				else {
					fprintf(stderr, "error: unsupported transport '%s', supported values: udp, tcp\n", optarg);
					exit_code(2);
				}
				break;
			case 'F':
				flood=1;
				break;
			case 'f':
				if (strlen(optarg) != 1 && STRNCASECMP(optarg, "-", 1) != 0) {
					/* file is opened in binary mode so that the cr-lf is 
					   preserved */
					pf = fopen(optarg, "rb");
					if (!pf){
						fprintf(stderr, "error: unable to open the file '%s'.\n", optarg);
						exit_code(2);
					}
					if (fread(buff, 1, sizeof(buff), pf) >= sizeof(buff)){
						fprintf(stderr, "error:the file is too big. try files of less "
							"than %i bytes.\n", BUFSIZE);
						fprintf(stderr, "      or recompile the program with bigger "
							"BUFSIZE defined.\n");
						exit_code(2);
					}
					fclose(pf);
				}
				else if (strlen(optarg) == 1 && STRNCASECMP(optarg, "-", 1) == 0) {
					if (read_stdin(&buff[0], sizeof(buff), 0) == 0) {
						exit_code(0);
					}
				}
				else {
					fprintf(stderr, "error: unable to handle input file name: %s\n", optarg);
					exit_code(2);
				}
				file_b=1;
				break;
			case 'g':
				replace_str=optarg;
				break;
			case 'G':
				replace_b=1;
				break;
			case 'h':
				print_help();
				break;
			case 'H':
				hostname=optarg;
				break;
			case 'i':
				via_ins=0;
				break;
			case 'I':
				invite=1;
				break;
			case 'j':
				headers=optarg;
				break;
			case 'l':
				lport=str_to_int(optarg);
				break;
			case 'L':
				fix_crlf=0;
				break;
			case 'm':
				maxforw=str_to_int(optarg);
				break;
			case 'M':
				message=1;
				break;
			case 'n':
				numeric = 0;
				break;
			case 'N':
				exit_mode=EM_NAGIOS;
				break;
			case 'o':
				sleep_ms = 0;
				if (strlen(optarg) == 4 && STRNCASECMP(optarg, "rand", 4) == 0) {
					sleep_ms = -2;
				}
				else {
					sleep_ms = str_to_int(optarg);
				}
				break;
			case 'O':
				con_dis=str_alloc(strlen(optarg) + 1);
				strncpy(con_dis, optarg, strlen(optarg));
				break;
			case 'p':
				parse_uri(optarg, &scheme, &user, &host, &rport);
				if (host == NULL) {
					fprintf(stderr, "error: missing in host in outbound proxy\n");
					exit_code(2);
				}
				if (is_ip(host)) {
					address = getaddress(host);
					if (transport == 0)
						transport = SIP_UDP_TRANSPORT;
				}
				else {
					if (!rport) {
						address = getsrvadr(host, &rport, &tsp);
						if (tsp != 0)
							transport = tsp;
					}
					if (!address) {
						address = getaddress(host);
						if (address && verbose > 1)
							printf("using A record: %s\n", host);
					}
					if (!address){
						fprintf(stderr, "error:unable to determine the outbound proxy "
							"address\n");
						exit_code(2);
					}
				}
				outbound_proxy=1;
				break;
			case 'P':
				processes=str_to_int(optarg);
				break;
			case 'q':
				if (re) {
					/* previously allocated -- free */
					regfree(re);
				} else {
					/* never tried -- allocate */
					re=malloc(sizeof(regex_t));
				};
				if (!re) {
					fprintf(stderr, "Error: can't allocate RE\n");
					exit_code(2);
				};
				if (regcomp(re, optarg, REG_EXTENDED|REG_ICASE|REG_NEWLINE )!=0) {
					fprintf(stderr, "Error: compiling RE: %s\n", optarg );
					exit_code(2);
				};
				break;
			case 'r':
				port = 0;
				port=str_to_int(optarg);
				if (rport) {
					fprintf(stderr, "warning: you are overwritting the destination port with the r argument\n");
				}
				rport = port;
				break;
			case 'R':
				randtrash=1;
				break;
			case 's':
				parse_uri(optarg, &scheme, &user, &host, &port);
				if (scheme == NULL) {
					fprintf(stderr, "error: missing scheme in sip uri\n");
					exit_code(2);
				}
				if (strlen(optarg) == 4 && STRNCASECMP(optarg,"sips",4) == 0){
					fprintf(stderr, "error: sips is not supported yet\n");
					exit_code(2);
				}
				else if (strlen(optarg) != 3 || STRNCASECMP(optarg,"sip",3) != 0){
					fprintf(stderr, "error: scheme of sip uri has to be sip\n");
					exit_code(2);
				}
				if (user != NULL) {
					username = user;
				}
				if (host != NULL) {
					domainname = host;
				}
				else {
					fprintf(stderr, "error: missing hostname in sip uri\n");
					exit_code(2);
				}
				if (port && !rport) {
					rport = port;
				}
				if (is_ip(domainname)) {
					address = getaddress(domainname);
					if (transport == 0)
						transport = SIP_UDP_TRANSPORT;
				}
				else {
					if (!rport && !address) {
						address = getsrvadr(domainname, &rport, &tsp);
						if (tsp != 0)
							transport = tsp;
					}
					if (!address) {
						address = getaddress(domainname);
						if (address && verbose > 1)
							printf("using A record: %s\n", domainname);
					}
					if (!address){
						fprintf(stderr, "error:unable to determine the IP address for: %s\n", domainname);
						exit_code(2);
					}
				}
				if (port != 0) {
					backup = str_alloc(strlen(domainname)+1+6);
					snprintf(backup, strlen(domainname)+6, "%s:%i", domainname, port);
					domainname = backup;
				}
				uri_b=1;
				break;
			case 'S':
				fprintf(stderr, "warning: symmetric does not work with a-symmetric servers\n");
				symmetric=1;
				break;
			case 't':
				trashchar=str_to_int(optarg);
				break;
			case 'T':
				trace=1;
				break;
			case 'U':
				usrloc=1;
				break;
			case 'u':
				auth_username=str_alloc(strlen(optarg) + 1);
				strncpy(auth_username, optarg, strlen(optarg));
				break;
			case 'v':
				verbose++;
				break;
			case 'V':
				printf("sipsak %s  by Nils Ohlmeier\n Copyright (C) 2002-2004"
						" FhG Fokus\n Copyright (C) 2004-2005 Nils Ohlmeier\n", 
						SIPSAK_VERSION);
				printf(" compiled with DEFAULT_TIMEOUT=%i, FQDN_SIZE=%i",
						DEFAULT_TIMEOUT, FQDN_SIZE);
#ifdef RAW_SUPPORT
				printf(", RAW_SUPPORT");
#endif
#ifdef HAVE_GETOPT_LONG
				printf(", LONG_OPTS");
#endif
#ifdef HAVE_GNUTLS
				printf(", GNUTLS_MD5");
#else
# ifdef HAVE_FULL_OPENSSL
				printf(", OPENSSL_MD5");
# else
				printf(", INTERNAL_MD5");
# endif
#endif
#ifdef HAVE_OPENSSL_SHA1
				printf(", OPENSSL_SHA1");
#endif
#ifdef HAVE_CARES_H
				printf(", SRV_SUPPORT(ARES)");
#else
# ifdef HAVE_RULI_H
				printf(", SRV_SUPPORT(RULI)");
# endif
#endif
#ifdef HAVE_STRCASESTR
				printf(", STR_CASE_INSENSITIVE");
#endif
#ifdef HAVE_STRNCASECMP
				printf(", CMP_CASE_INSENSITIVE");
#endif
				printf("\n");
				exit_code(0);
				break;
			case 'w':
				warning_ext=1;
				break;
			case 'W':
				nagios_warn = str_to_int(optarg);
				break;
			case 'x':
				expires_t=str_to_int(optarg);
				break;
#ifdef HAVE_GETOPT_LONG
			case 'X':
				print_long_help();
				break;
#endif
			case 'z':
				rand_rem=str_to_int(optarg);
				if (rand_rem < 0 || rand_rem > 100) {
					fprintf(stderr, "error: z option must between 0 and 100\n");
					exit_code(2);
				}
				break;
			default:
				fprintf(stderr, "error: unknown parameter %c\n", c);
				exit_code(2);
				break;
		}
	}

	if (rport == 0) {
		rport =  5060;
	}
	if (rport > 65535 || rport <= 0) {
		fprintf(stderr, "error: invalid remote port: %i\n", rport);
		exit_code(2);
	}
	if (transport == 0) {
		transport = SIP_UDP_TRANSPORT;
	}

	/* replace LF with CRLF if we read from a file */
	if ((file_b) && (fix_crlf)) {
		insert_cr(buff);
	}
	if (headers) {
		backup = str_alloc(strlen(headers) + 30); // FIXME
		strcpy(backup, headers);
		headers = backup;
		replace_string(headers, "\\n", "\r\n");
		backup = headers + strlen(headers) - 1;
		if (*backup != '\n') {
			strcpy(backup + 1, "\r\n");
		}
		if (file_b)
			insert_header(buff, headers, 1);
	}
	/* lots of conditions to check */
	if (trace) {
		if (usrloc || flood || randtrash) {
			fprintf(stderr, "error: trace can't be combined with usrloc, random or "
				"flood\n");
			exit_code(2);
		}
		if (!uri_b) {
			fprintf(stderr, "error: for trace mode a SIPURI is realy needed\n");
			exit_code(2);
		}
		if (file_b) {
			fprintf(stderr, "warning: file will be ignored for tracing.");
		}
		if (!username) {
			fprintf(stderr, "error: for trace mode without a file the SIPURI have to "
				"contain a username\n");
			exit_code(2);
		}
		if (!via_ins){
			fprintf(stderr, "warning: Via-Line is needed for tracing. Ignoring -i\n");
			via_ins=1;
		}
		if (!warning_ext) {
			fprintf(stderr, "warning: IP extract from warning activated to be more "
				"informational\n");
			warning_ext=1;
		}
		if (maxforw==-1) maxforw=255;
	}
	else if (usrloc || invite || message) {
		if (trace || flood || randtrash) {
			fprintf(stderr, "error: usrloc can't be combined with trace, random or "
				"flood\n");
			exit_code(2);
		}
		if (!username || !uri_b) {
			fprintf(stderr, "error: for the USRLOC mode you have to give a SIPURI with "
				"a username\n       at least\n");
			exit_code(2);
		}
		if (namebeg>0 && nameend==-1) {
			fprintf(stderr, "error: if a starting numbers is given also an ending "
				"number have to be specified\n");
			exit_code(2);
		}
		if (invite && message) {
			fprintf(stderr, "error: invite and message tests are XOR\n");
			exit_code(2);
		}
		if (!usrloc && invite && !lport) {
			fprintf(stderr, "warning: Do NOT use the usrloc invite mode without "
				"registering sipsak before.\n         See man page for "
				"details.\n");
			exit_code(2);
		}
		if (contact_uri!=NULL) {
			if (invite || message) {
				fprintf(stderr, "error: Contact uri is not support for invites or "
					"messages\n");
				exit_code(2);
			}
			if (nameend!=-1 || namebeg!=-1) {
				fprintf(stderr, "warning: ignoring starting or ending number if Contact"
					" is given\n");
				nameend=namebeg=0;
			}
			if (rand_rem) {
				fprintf(stderr, "warning: ignoring -z option when Contact is given\n");
				rand_rem=0;
			}
		}
		if (via_ins) {
			fprintf(stderr, "warning: ignoring -i option when in usrloc mode\n");
			via_ins=0;
		}
		if (nameend==-1)
			nameend=0;
		if (namebeg==-1)
			namebeg=0;
	}
	else if (flood) {
		if (trace || usrloc || randtrash) {
			fprintf(stderr, "error: flood can't be combined with trace, random or "
				"usrloc\n");
			exit_code(2);
		}
		if (!uri_b) {
			fprintf(stderr, "error: we need at least a sip uri for flood\n");
			exit_code(2);
		}
		if (redirects) {
			fprintf(stderr, "warning: redirects are not expected in flood. "
				"disableing\n");
			redirects=0;
		}
	}
	else if (randtrash) {
		if (trace || usrloc || flood) {
			fprintf(stderr, "error: random can't be combined with trace, flood or "
				"usrloc\n");
			exit_code(2);
		}
		if (!uri_b) {
			fprintf(stderr, "error: need at least a sip uri for random\n");
			exit_code(2);
		}
		if (redirects) {
			fprintf(stderr, "warning: redirects are not expected in random. "
				"disableing\n");
			redirects=0;
		}
		if (verbose) {
			fprintf(stderr, "warning: random characters may destroy your terminal "
				"output\n");
		}
	}
	else if (mes_body) {
		if (!message) {
			fprintf(stderr, "warning: to send a message mode (-M) is required. activating\n");
			message=1;
		}
		if (!uri_b) {
			fprintf(stderr, "error: need at least a sip uri to send a meesage\n");
			exit_code(2);
		}
		if (nameend==-1)
			nameend=0;
		if (namebeg==-1)
			namebeg=0;
	}
	else {
		if (!uri_b) {
			fprintf(stderr, "error: a spi uri is needed at least\n");
			exit_code(2);
		}
	}

	switch (transport) {
		case SIP_TLS_TRANSPORT:
			transport_str = TRANSPORT_TLS_STR;
			break;
		case SIP_TCP_TRANSPORT:
			transport_str = TRANSPORT_TCP_STR;
			break;
		case SIP_UDP_TRANSPORT:
			transport_str = TRANSPORT_UDP_STR;
			break;
		default:
			fprintf(stderr, "unknown transport: %i\n", transport);
			exit_code(2);
	}

	/* determine our hostname */
	get_fqdn();
	
	/* this is not a cryptographic random number generator,
	   but hey this is only a test-tool => should be satisfying*/
	srand(time(0) ^ getpid());
	
	if (processes > 1) {
		if (signal(SIGCHLD , sigchld_handler)  == SIG_ERR ) {
			fprintf(stderr, "error: Could not install SIGCHLD handler\n");
			exit_code(2);
		}
	}

	for(i = 0; i < processes - 1; i++) {
		if ((pid = fork()) < 0) {
			fprintf(stderr, "error: Cannot fork\n");
			exit_code(2);
		}
		
		if (pid == 0){
	    	/* child */
			upp = (nameend - namebeg + 1) / processes;
			namebeg = namebeg + upp * i;
			nameend = namebeg + upp;
			shoot(&buff[0], sizeof(buff));
		} else {
			if (lport) {
				lport++;
			}
		}
		
		/* Delay execution of children so that the
		 * time of the first transmission gets spread over
		 * the retransmission interval evenly
		 */
		ts.tv_sec = 0;
		ts.tv_nsec = (float)DEFAULT_TIMEOUT / (float)processes * (float)1000 * (float)1000;
		nanosleep(&ts, 0);
	}

	/* here we go...*/
	if (processes > 1) {
		upp = (nameend - namebeg + 1) / processes;
		namebeg = namebeg + upp * i;
		nameend = namebeg + upp;
	}
	shoot(&buff[0], sizeof(buff));

	/* normaly we won't come back here, but to satisfy the compiler */
	return 0;
}
Example #12
0
void *
http_go_proc(task_t *t)
{
  int index = TASK_THRINDEX(t);
  Request h;
  ArgumentList prefs;
  userkey k;
  HTTP_Status result;
  DistillerStatus dist_result;
  const char *content_type;
  Argument *arg;
  int thresh;
  gm_Bool no_distill = gm_False;
  gm_Bool is_text_html = gm_False;
#ifdef LOGGING
  struct loginfo lo;
  char logmsg[MAX_LOGMSG_LEN];
#endif /* LOGGING */
  
  /*
   *  New task data should be the request structure.
   */
  init_Request(&h);
  h.cli_fd = (int)TASK_DATA(t); /* socket FD of client */
  SET_TASK_DATA(t,&h);
  
  INST_begin_timestamp(index);
  INST_set_size(index,0);
  INST_set_thread_state(index, THR_ACCEPTED);
  INST_timestamp(index, m_arrival);
#ifdef LOGGING
  LOGGING_init_loginfo(&lo);
  h.lo = &lo;
#endif /* LOGGING */
  /*
   *  this should read all the headers.
   */
  if (TASK_METADATA(t) == NULL) {
    int result;
    
    assert( DistillerBufferAlloc(&h.cli_hdrs, PERF_HTTP_TOTAL_HEADERLEN)
            == gm_True);

    result = readline_or_timeout(&h, READ_ALL_HEADERS, NULL);

    INST_timestamp(index, m_headersdone);
    if (result == -1) { /* client request timed out, or error reading hdrs */
      /* TC::1 client timeout, or request doesn't sanity check */
      goto HTTPGO_FINISH;
      /* NOTREACHED */
    }
  } else {
#ifdef NEWFE
    /*
     *  This task is a child of a previous 
     */
    strncpy(h.cli_hdrs.mime_headers, TASK_METADATA(t),
            PERF_HTTP_TOTAL_HEADERLEN-1);
    FREE(TASK_METADATA(t));
#endif /* NEWFE */
  }

  /* parse the headers and request line, filling them in to the loginfo */
  result = parse_status_and_headers(&h);
  if (result != HTTP_NO_ERR) {
    /* BUG:: last arg of http_error_return should be a substitution arg */
    /* TC::2 parse_status_and_headers returns an error */
    http_error_return(&h, result);
    printf("Error occured here!\n");
    goto HTTPGO_FINISH;
  }
  
  /*
   *  We have a reasonable looking request.  Get prefs for this user.
   */

  k = userkey_from_sock_ipaddr(h.cli_fd);
#ifdef LOGGING
  lo.ipaddr = k;
#endif /* LOGGING */
  (void)get_userprefs(k, &prefs);
  /*
   *  Extract any arguments embedded in the URL itself, and add them
   *  to the arg list.
   *  TC::3 url is magic vs nonmagic
   */
  if (is_magic ((char *) h.url)) {
    /* demagifying a url will never lengthen it so this is a good 
     * upper bounds on the length of the non magical url
     */
    char *demagicURL = ALLOCA(strlen(h.url)+1);
    assert(demagicURL);
    strcpy(demagicURL, h.url);
    from_magic((char *) demagicURL, h.url, &prefs);
  }

  /* determine the threshold for bypassing */
  arg  = getArgumentFromIdInList(&prefs, FRONT_MTU);
  thresh = (arg == NULL ? PERF_FRONT_MTU : ARG_INT(*arg));

  /* determine if distillation is turned off for this
   * request. EXCEPTION: Force distillation for Prefs html form.
   */
  arg = getArgumentFromIdInList(&prefs, FRONT_NO_DISTILL);
  if (arg != NULL
      && ARG_INT(*arg)
      && strcasecmp(fe_get_prefs_url, h.url) != 0) {
    /* TC::4 no_distill is set */
    no_distill = gm_True;
  }  else {
    no_distill = gm_False;
  }
  
  /* Short-circuit the following special  URL's:
   *  - "set my prefs as follows" (e.g. form submission)
   */
  if (is_setpref_url(h.url)) {
    /* 
     * handle what send user prefs form sends back.
     * TC::5 is_setpref_url returns true
     */
    result = parse_and_change_prefs(h.url, k, h.errmsg);
    if (result == HTTP_NO_ERR) {
      /* TC::5.1 setpref url succeeds in setting prefs */
      correct_write(h.cli_fd, "HTTP/1.0 200\r\nContent-type: text/html\r\n\r\n",
                    -1);
      correct_write(h.cli_fd,
                    "<html><head><title>Preferences Set</title></head>"
                    "<body><center><h1>Preferences set</h1>"
                    "Your new preferences have been set.  Press the back "
                    "button twice to resume browsing."
                    "<p></center></body></html>", -1);
    } else {
      /* TC::5.2 setpref url fails in setting prefs */
      http_error_return(&h, result);
    }
  } else if (is_getpref_url(h.url)) {
    /* TC::6 gimme my prefs*/
    send_prefs(&prefs, h.cli_fd);
  } else if (is_server_url(h.url)==gm_False   && 
	     strcasecmp(h.method, "get") != 0 && 
	     strcasecmp(h.method, "post") != 0) {
    /*
     *  Doesn't appear to be an HTTP GET or POST request; so act as a
     *  "dumb tunnel" for passing the request to the server (actually, via
     *  the cache) and relaying the result to the client.
     */
    /* TC::7 tunnel */
    proxy_debug_3(DBG_HTTP, "Tunneling '%s'", 
		  DistillerBufferData(&h.cli_hdrs));
    INST_set_thread_state(index, THR_DISTILLERSEND);
    tunnel(&h);
  } else {
    /*
     *  It's not a special URL, and the request appears to be a GET/POST.
     * Add in the client's IP address as an INT32 argument so that
     *  the distiller driver can get at it.
     */
    SET_ARG_INT(prefs.arg[prefs.nargs], (INT32) k);
    SET_ARG_ID(prefs.arg[prefs.nargs], FRONT_CLIENT_IP);
    prefs.nargs++;
    result = server_dispatch(&prefs, t);
    /*
     *  If we get a transport-level error (i.e. fetch from cache failed
     *  due to an internal cache error), wrap the error in HTML (if
     *  needed) and return error to user.
     *  Otherwise, if the transaction succeeded but the server return
     *  code indicates failure (i.e. != 200),  **OR** if the server data
     *  is smaller than a threshold size, bypass the server data
     *  directly to the client.
     *  Otherwise, attempt to distill.
     */
    if (result != HTTP_NO_ERR) {
      /* transport level error: wrap in HTML for delivery to user */
      /* TC::8 server_dispatch returns transport level error */
      http_error_return(&h, result);
      goto HTTPGO_FINISH;
    }

    content_type = get_header_value(&h.svr_hdrs,
                                    "content-type", NULL, NULL, NULL);
    if (content_type == NULL) {
      /* TC::9 content-type can't be deduced */
      content_type = "application/octet-stream";
    }
    is_text_html = (  ((strncasecmp(content_type, "text/html", 9) == 0) ||
                       (strncasecmp(content_type, "text/plain", 10) == 0))
                    ? gm_True : gm_False);
    
    /*if ( (*h.url != '/' && strncasecmp(h.url, fe_agg_string, 
				       strlen(fe_agg_string)) != 0) &&*/

    /* bypass ONLY if it is not a server-type URL */
    /* TC::10.1 bypass because non-200s status */
    /* TC::10.2 bypass because not text/html and too small to distill */
    /* TC::4 bypass because no_distill is set */
    /* bypass server data directly to user */

    if ( is_server_url(h.url)==gm_False) {
      char *bypass_reason = NULL;
      if (h.svr_http_status != 200) {
        bypass_reason = "201 Non-OK server status";
      } else if (is_text_html == gm_False
                 && DistillerBufferLength(&h.svr_data) <= thresh) {
        bypass_reason = "202 content-type not text/html and content-length too short";
      } else if (no_distill == gm_True) {
        bypass_reason = "203 distillation not indicated";
      }
      if (bypass_reason) {
        INST_set_thread_state(index, THR_WRITEBACK);
        /*
         *  Set return headers to indicate why the bypass occurred.
         */
        insert_header(&h.svr_hdrs, TRANSEND_STATUS_HEADER, bypass_reason, 0);
        complete_bypass(&h);
        goto HTTPGO_FINISH;
      }
    }
    
    /* all is well: continue by dispatching to a worker for distillation */
    dist_result = proxy_dispatch(&prefs, t);
    switch(dist_result) {
    case distOk:
      /* TC::11 distillation succeeded */
      INST_timestamp(index, m_wbstart);
      insert_header(&h.pxy_hdrs, TRANSEND_STATUS_HEADER, "200 distillation OK", 0);
      correct_write(h.cli_fd, (char *)DistillerBufferData(&h.pxy_hdrs),
                    (int)DistillerBufferLength(&h.pxy_hdrs));
      /* -1 to avoid NULL term gunk */
      correct_write(h.cli_fd, (char *)DistillerBufferData(&h.pxy_data),
                    (int)DistillerBufferLength(&h.pxy_data));
      INST_timestamp(thrindex, m_wbdone);
      break;

    case distDistillerNotFound:
    case distLaunchTimeout:
    case distBadInput:
    case distConnectionBroken:

      /* forward original if distiller for this type not found, connection
         repeatedly broken, or couldn't be launched */
      /* TC::12 bypass because distillation failed */

      insert_header(&h.svr_hdrs,
                      (dist_result == distBadInput ? TRANSEND_STATUS_HEADER
                       : TRANSEND_ERROR_HEADER),
                      FE_getDistillerStatusString(dist_result), 0);
      if ((arg = getArgumentFromIdInList(&prefs, FRONT_DEVELOPER))
          && ARG_INT(*arg)) {
        /* return explicit error message */
        int tmp_len =
          snprintf(h.errmsg, HTTP_ERRMSG_MAX,
                   "<i>[set arg <tt>i%d</tt> to 0 to suppress "
                   "this diagnostic]</i><br>",
                   FRONT_DEVELOPER);
        strncat(h.errmsg, FE_getDistillerStatusString(dist_result),
                HTTP_ERRMSG_MAX - tmp_len - 1);
        http_error_return(&h, HTTP_ERR_UNSPECIFIED);
      } else {

        /*if (*h.url == '/' || 
	    strncasecmp(h.url, fe_agg_string, strlen(fe_agg_string)) == 0) {*/

        if (is_server_url(h.url)==gm_True) {
          /* this is a URL in the frontend's namespace, or an aggregator URL */

          strcpy(h.errmsg, h.url);
          http_error_return(&h, HTTP_ERR_AGGREGATOR_ERROR);
        } else {
          complete_bypass(&h);
        }
      }
    break;
        
    case distRedispatch:
      /*
       *  Redispatch count expired: too many redispatches (probably indicates
       * infinite loop in redispatch route.)
       */
      snprintf(h.errmsg, HTTP_ERRMSG_MAX, "%d", PERF_REQUEST_TTL);
      http_error_return(&h, HTTP_ERR_ROUTING_ERROR);
      break;
      
    default:
        
      /* TC::13 some other distillation error */
      insert_header(&h.svr_hdrs, TRANSEND_STATUS_HEADER,
                    FE_getDistillerStatusString(dist_result), 0);

      http_error_return(&h, HTTP_ERR_UNSPECIFIED);
      break;
    } /* switch(dist_result) */
  } /* if...else...else...endif */

  /* all cases exit through this single exit point */
HTTPGO_FINISH:
  free_Request(&h);
  INST_timestamp(index, m_wbdone);
  INST_end_timestamp(index);

  if (TASK_PARENT(t) == 0 && TASK_CHILD_INDEX(t) == 0) {
    /* this is a "root task" */
    close(h.cli_fd);
  }

#ifdef LOGGING
  /* log the request info */
  /* BUG::relies on formatting of the userkey */

  /* I compare the IP address to 127.0.0.1 so that I don't log connections
     from localhost, namely the fe_check script.  I also MD5 the IP address. */
  k = lo.ipaddr;
  if (((UINT32) k) != ((UINT32) htonl(0x7F000001))) {
/*    MD5_CTX   theHash;
    UINT32    res;

    MD5Init(&theHash);
    MD5Update(&theHash, magicKey, sizeof(magicKey));
    MD5Update(&theHash, &k, sizeof(UINT32));
    MD5Final(&theHash);

    memcpy(&res, theHash.digest, sizeof(UINT32));
    res = ntohl(res);

    snprintf(logmsg, MAX_LOGMSG_LEN-1,
             "(HTTP) %lu %lu \"%s\" %d %ld %ld\n",
             res, lo.date, lo.url,
             lo.http_response, lo.size_before, lo.size_after);*/
    snprintf(logmsg, MAX_LOGMSG_LEN-1,
             "(HTTP) %08x %08x \"%s\" %d %ld %ld\n",
             (UINT32) k, lo.date, lo.url,
             lo.http_response, lo.size_before, lo.size_after);
    gm_log(logmsg);
  }
#endif /* LOGGING */
  return (void *)0;
}
Example #13
0
/* void protocol1
 *   buffer* recv_buffer - buffer containing the message sent by the client to the proxy
 *   server_stat* status - status and general information from the server
 * Processes the recv_buf as the class protocol dictates
 */
void protocol1(buffer* recv_buf, server_stat* status){
    struct timeval timeout;
    struct timeval timeout_0;
    // timeouts
    timeout.tv_sec = 1;
    timeout.tv_usec = 0;
    timeout_0.tv_sec = 0;
    timeout_0.tv_usec = 0;

    timeout_setup(status->udp_sock, timeout);

    // giant mess of conditionals
    fprintf(stdout, "\tversion 1 protocol\n");
    int error = 0;
    header msg_header = extract_header(recv_buf);
    if (status->connected == 0) {
        if (check_pass(&msg_header, 0)) {
            if (get_command(&msg_header) == CONNECT) {
                fprintf(stdout, "\tReplying with password\n");
                status->connected = 1;
                msg_header.data[1] = status->password;
                insert_header(recv_buf, msg_header);
                if (udp_send(recv_buf, status) < 0) {
                    fprintf(stderr, "sendto()\n");
                }
            } else {
                fprintf(stderr, "ERROR: Unexpected Command\n");
                error = -2;
            }
        } else {
            fprintf(stderr, "ERROR: Incorrect Password\n");
        }
    } else if (status->connected == 1) {
        if (check_pass(&msg_header, status->password)) {
            if (get_command(&msg_header) == CONNECT) {
                status->connected = 2;
                timeout_setup(status->udp_sock, timeout_0);
                fprintf(stdout, "\tConnected to a client\n");
            } else {
                fprintf(stderr, "ERROR: Unexpected Command\n");
                error = -2;
            }
        } else {
            fprintf(stderr, "ERROR: Incorrect Password\n");
            error = -2;
        }
    } else {
        if (!check_pass(&msg_header, status->password)) {
            fprintf(stderr, "ERROR: Incorrect Password\n");
                error = -2;
        } else {
            fprintf(stdout, "\t\tReceived Message:\n");
            print_header(recv_buf);
            switch (get_command(&msg_header)) {
                case CONNECT:
                    fprintf(stderr, "ERROR: Unexpected Command\n");
                error = -2;
                    break;
                case QUIT:
                    quit(recv_buf, status);
                    timeout_setup(status->udp_sock, timeout_0);
                    break;
                default:
                    error = request_command(recv_buf, status);
                    break;
            }
        }
    }
    if (error == -2) {
        fprintf(stderr, "ERROR: Invalid client request\n");
        send_error(status, CLIENT_ERROR);
    } else if (error == -1) {
        fprintf(stderr, "ERROR: Problem with http response\n");
        send_error(status, HTTP_ERROR);
    }
}
Example #14
0
HTTP_Status
server_dispatch(ArgumentList *al, task_t *tsk)
{
  int thrindex = TASK_THRINDEX(tsk);
  int agg = 0;
  int nfound;
  HTTP_Status retcode = HTTP_NO_ERR;
  Request *hp = (Request *)TASK_DATA(tsk);
#ifdef LOGGING
  struct loginfo *lo = hp->lo;
#endif

  INST_set_thread_state(thrindex, THR_CACHE);

  /*
   *  If we got here, we know the request is either GET or POST,
   *  or this is a URL in the frontend's namespace
   */

  tsk->task_age = 0;            /* no pipe stages done yet */

  /*if (*hp->url == '/' || 
      strncasecmp(hp->url, fe_agg_string, strlen(fe_agg_string)) == 0) {*/
  if (is_server_url(hp->url)==gm_True) {
    /* this is a URL in the frontend's namespace, or an aggregator URL */
    const char *workerName, *val;
    int val_len, len, to_copy, already_read;
    char *orig_hdrs, *eoh, *new_hdrs, *body;
    extern Options runtime_options;

    orig_hdrs = DistillerBufferData(&hp->cli_hdrs);
    eoh = strstr(orig_hdrs, "\r\n\r\n");
    if (eoh==NULL) {
      retcode = HTTP_ERR_MALFORMED_REQUEST;
      goto DISPATCH_RETURN;
    }
    eoh += 4;

    /* clone the headers */
    DistillerBufferAlloc(&hp->svr_hdrs, eoh-orig_hdrs+1);
    new_hdrs = DistillerBufferData(&hp->svr_hdrs);
    memcpy(new_hdrs, orig_hdrs, eoh-orig_hdrs);
    *(new_hdrs+(eoh-orig_hdrs)) = '\0';
    DistillerBufferSetLength(&hp->svr_hdrs, eoh - orig_hdrs);
    DistillerBufferFreeMe(&hp->svr_hdrs, gm_True);

    /* 
     * look for the content-length field; 
     * if found, read the rest of the data and create svr_data 
     */
    if ((val = get_header_value(&hp->cli_hdrs, "content-length", &val_len,
				NULL, NULL)) != NULL) {
      len = strtoul(val, NULL, 0);
      if (len < 0) {
	retcode = HTTP_ERR_MALFORMED_REQUEST;
	goto DISPATCH_RETURN;
      }

      already_read = DistillerBufferLength(&hp->cli_hdrs) - (eoh - orig_hdrs);
      if (len <= already_read) {
	to_copy = len;
      } else {
	to_copy = already_read;
      }

      DistillerBufferAlloc(&hp->svr_data, len+1);
      body = DistillerBufferData(&hp->svr_data);
      memcpy(body, eoh, to_copy);
      
      /* get the rest of the data from the socket */
      if (to_copy < len) {
	if (readline_or_timeout(hp, len - to_copy, body+to_copy)
	    != (len-to_copy)) {
	  retcode = HTTP_ERR_MALFORMED_REQUEST;
	  goto DISPATCH_RETURN;
	}
      }

      /* add a trailing '\0' */
      *(body+len) = '\0';
      DistillerBufferSetLength(&hp->svr_data, len);
    }
    
    workerName = Options_Find(runtime_options, "frontend.myurl.dispatch");
    if (workerName==NULL) workerName = "myurl/dispatch";

    insert_header(&hp->svr_hdrs, "X-Route", workerName, 1);
    hp->svr_http_status = 200; /* everything's ok with this HTTP request */
  }
  else {
    INST_timestamp(thrindex, m_cachestart);
    if (hp->method[0] == 'g' || hp->method[0] == 'G') {
      /* handle GET */

#ifdef OLD
      /*
       *  HACK HACK HACK - this should be replaced with the real interface that
       *  does a regexp match on URL to determine if any aggregator should get
       *  dibs before the original content is fetched.
       *
       *  Any references in this function to variable 'agg' represent a place
       *  where the hack was spliced in.
       */
      if (strncasecmp(hp->url, fe_agg_string, strlen(fe_agg_string)) != 0) {
	/* not an aggregator call */
#endif
	agg = 0;
	retcode = do_get(hp, al);
	if (retcode != HTTP_NO_ERR) {
	  goto DISPATCH_RETURN;
	}
#ifdef OLD
      } else {
	/* aggregator call */
	abort();
	agg = 1;
	/* don't clone the client headers - just point to them. */
	DistillerBufferSetStatic(&hp->svr_hdrs,
				 DistillerBufferData(&hp->cli_hdrs),
				 DistillerBufferLength(&hp->cli_hdrs));
	/* since we're pointing to a copy, don't try to free */
	DistillerBufferFreeMe(&hp->svr_hdrs, gm_False);
      }
#endif
    } else {
      /* handle POST */
      retcode = do_post(hp, al);
      if (retcode != HTTP_NO_ERR) {
	/* post failed! report error to client */
	goto DISPATCH_RETURN;
      }
    }

    INST_timestamp(thrindex, m_cachedone);

    /*
     *  if there was an HTTP-level error (response code not "200"), bypass
     *  the remainder straight to client.
     */
    
    nfound = sscanf(DistillerBufferData(&hp->svr_hdrs), "%*s %lu",
		    &hp->svr_http_status);
    if (nfound < 1) {             /* no status found */
      retcode = HTTP_ERR_GET_FAILED;
      hp->svr_http_status = 0;
    } else {
      retcode = HTTP_NO_ERR;
    }
  }

#ifdef LOGGING
  lo->http_response = hp->svr_http_status;;      /* log HTTP server response */
#endif /* LOGGING */

  /*
   *  Note that HTTP_NO_ERR means "transaction to server succeeded" (ie
   *  at the transport level).  it does NOT necessarily mean that the
   *  HTTP *operation* (eg GET) succeeded -- the HTTP status code tells that.
   */

DISPATCH_RETURN:
  return retcode;
}
Example #15
0
DistillerStatus
proxy_dispatch(ArgumentList *al, task_t *t)
{
  DistillerStatus status;       /* result of this pipe stage distillation */
  DistillerInput din;
  DistillerOutput dout;
  Request *hp = (Request *)TASK_DATA(t);
  C_DistillerType dtype;
  int thrindex = TASK_THRINDEX(t);
  DistillerStatus retcode;
  int redispatch = 0;
  char *static_route = NULL;
  int static_route_initialized = 0;
#ifdef LOGGING
  struct loginfo *lo = hp->lo;
#endif

  /*
   *  Initialize for *first* pipe stage.
   */

  DistillerBufferClone(&din.data, &hp->svr_data);
  DistillerBufferFreeMe(&din.data, gm_True);

  /*
   *  Make a **copy** of the server headers, because they may get
   *  overwritten when preparing headers to send to a distiller.
   */
  DistillerBufferClone(&din.metadata, &hp->svr_hdrs);
  DistillerBufferFreeMe(&din.metadata, gm_True);
  
  do {
    const char *char_tmp;
    char content_type[MIME_TYPE_MAX+1];
    int content_type_len;
    Argument *arg;
    int num_tries_left;

    /*
     *  Initialize for next pipe stage.
     */
    status = distFatalError;

#ifdef LOGGING
    /*
     *   Log original content-length
     */
    char_tmp = get_header_value(&din.metadata,
                                "content-length",
                                &content_type_len, NULL, NULL);
    if (char_tmp != NULL)
      lo->size_before = strtoul(char_tmp, NULL, 0);
    else
      lo->size_before = -1;
#endif /* LOGGING */
    char_tmp = get_header_value(&din.metadata,
                                "content-type",
                                &content_type_len, NULL, NULL);
    if (char_tmp != NULL) {
      strncpy(content_type, char_tmp, MIN(content_type_len+1, MIME_TYPE_MAX));
      content_type[MIN(content_type_len,MIME_TYPE_MAX)] = '\0';
    } else {
      content_type[0] = '\0';
    }

    /* if there are attributes after the content-type, remove them. */
    if ((char_tmp = strchr((const char *)content_type, ';')) != NULL)
      *(char *)char_tmp = '\0';
    /* chop any trailing spaces. */
    if ((char_tmp = strchr((const char *)content_type, ' ')) != NULL)
      *(char *)char_tmp = '\0';

    /*
     *  Distillation is definitely needed, so go do it.  In case of
     *  distConnectionBroken error, (re)try at most N
     *  times, where N is the value of the FRONT_RETRY_DISTILL argument,
     *  or PERF_HTTP_RETRY_DISTILL by default.  In case of any other
     *  error, or if all retries fail, bypass the original content.  In
     *  case of distOk (success), return the distilled content.
     */

    arg = getArgumentFromIdInList(al, FRONT_RETRY_DISTILL);
    num_tries_left = (arg ? ARG_INT(*arg) : PERF_HTTP_RETRY_DISTILL);
    INST_timestamp(thrindex, m_distillstart);
    /*
     *  Add a "Location:" header so distillers have a way to get the URL of
     *  this document, if they want. 
     */
    if (get_header_value(&din.metadata,
                         "location", NULL, NULL, NULL)
        == NULL) {
      insert_header(&din.metadata, "Location", hp->url, 0);
    }

    do {
      INST_set_thread_state(thrindex, THR_DISTILLER);
      status = do_distillation(hp->url, &din, &dout, &dtype, al);
    } while (status == distConnectionBroken
             && num_tries_left-- > 0);

#ifdef LOGGING
    lo->size_after = -status;     /* pessimistically assume failure for log */
#endif /* LOGGING */

    switch(status) {
    case distOk:
    case distRedispatch:
      /*
       *  The rules for redispatch are as follows.
       *  - If the response headers contain a nonempty X-Static-Route header, it
       *    is the final authority. X-Static-Route is only saved the
       *    first time it's seen.
       *  - Otherwise, if the response code is distRedispatch, use the
       *    default rules to figure out who to go to next.
       *  - Otherwise, the response is distOk --> just finish.
       */

      if (! static_route_initialized
          && DistillerBufferLength(&dout.metadata) > 0) {
        /* look for X-Static-Route */
        int tmp_len;
        const char *static_route_hdr =
          get_header_value(&dout.metadata,
                           "x-static-route", &tmp_len, NULL, NULL);
        if (static_route_hdr != NULL && tmp_len > 0) {
          static_route = ALLOCA(tmp_len+1);
          strncpy(static_route, static_route_hdr, tmp_len);
          static_route[tmp_len] = '\0';
          static_route_initialized = 1;
          delete_header(&dout.metadata, "x-static-route");
        }
      }

      if (static_route ||
          (status == distRedispatch && !static_route_initialized)) {
        /*
         *  this is a redispatch.
         *  The redispatch strategy is as follows.  Since the
         * DistillerInput pointer starts out being  a *clone* of the
         * server headers and data, it's always safe to free it.  THen move the
         *  DistillerOutput pointer (result of previous pipestage) to the
         *  DistillerInput pointer of this pipestage.  
         */

        DistillerBufferFree(&din.metadata);
        DistillerBufferFree(&din.data);
        DistillerBufferClone(&din.metadata, &dout.metadata);
        DistillerBufferClone(&din.data, &dout.data);
        DistillerBufferFree(&dout.metadata);
        DistillerBufferFree(&dout.data);

        /*
         *  Fix the content-length and content-type, if nec.
         */
        if (get_header_value(&din.metadata, "content-type",NULL,NULL,NULL)
            == NULL)
          insert_header(&din.metadata, "Content-type", din.mimeType, 1);
        if (get_header_value(&din.metadata, "content-length", NULL,NULL,NULL)
            == NULL) {
          char __tmp[12];
          snprintf(__tmp, 11, "%lu", DistillerBufferLength(&din.data));
          insert_header(&din.metadata, "Content-length", __tmp, 1);
        }
        if (static_route) {
          status = distRedispatch;
          /* add the X-Route header to this request */
          insert_header(&din.metadata, "X-Route", static_route, 1);
          /* scan forward to the next component of the path */
          while (*static_route && (*static_route != ';')) {
            static_route++;
          }
          if (*static_route == '\0') {
            static_route = NULL;
          } else {
            /* skip semicolon and any spaces */
            while (*static_route && ((*static_route == ';')
                                     || (*static_route == ' '))) {
              static_route++;
            }
            if (*static_route == '\0')
              static_route = NULL;
          }
        }
        redispatch++;
        t->task_age++; /* "time to live" of this request */
        retcode = distRedispatch;
      } else {
        /*
         *  Here if any of the following were true:
         *  - status was distOk and no static route header overrides this
         *  - status was distRedispatch, but an existing static route header
         *     indicates that we should override and finish with 
         */
#ifdef LOGGING
        lo->size_after = DistillerBufferLength(&dout.data);
#endif /* LOGGING */
        status = retcode = distOk;
      }
      break;

    default:                    /* some other distiller/ptm error */
      /*
       *  BUG::we shouldn't make this visible to the user unless the
       * "guru" argument is set
       */
      snprintf(hp->errmsg, HTTP_ERRMSG_MAX,
               (char *)FE_getDistillerStatusString(status));
      /*      retcode = HTTP_ERR_DISTILLER; XXX - XXX - XXX - */
      retcode = status;
      break;
      
    } /* switch(status) */

    /* Note that the data size is set last.  So if the data size is not zero,
       it's a reasonable indication that this is a compelte set of valid
       measurements.  (should really have a separate valid bit)
       */
    INST_set_size(thrindex, DistillerBufferLength(&dout.data));

  }  while ((status == distRedispatch)
            &&  t->task_age <= PERF_REQUEST_TTL);  /* do */
  
  /*
   *  "Copy" final output buffer to hp->pxy_hdrs/hp->pxy_data.  (Really
   *  we just copy the pointers, since the pxy_hdrs/pxy_data buffers
   *  will be freed by the caller.)
   *
   *  First generate headers to return to client.  If last-stage
   *  distiller returned
   *  some headers, use them; otherwise, replace the "content-length"
   *  and "content-type" fields of the ORIGINAL server headers with
   *  new values deduced from the distiller data.
   */
  if (status == distOk) {
    if (DistillerBufferLength(&(dout.metadata)) > 0) {
      DistillerBufferClone(&hp->pxy_hdrs, &dout.metadata);
    } else {
      /*
       *  If the server headers begin with an HTTP/x.x response code, they are
       *  headers from an origin server; OK to clone them and just replace the
       *  content-type and content-length.  Otherwise, they are probably
       *  the result of a server-mode dispatch worker, which means they
       *  actually look like request headers (not response headers), so delete them.
       */
      if (DistillerBufferLength(&hp->svr_hdrs) > 0
          && strncasecmp(DistillerBufferData(&hp->svr_hdrs), "HTTP/", 5) == 0) {
        DistillerBufferClone(&hp->pxy_hdrs, &hp->svr_hdrs);
        delete_header(&hp->pxy_hdrs,  "content-type");
        delete_header(&hp->pxy_hdrs,  "content-length");
      } else {
        char *s = "HTTP/1.0 200 OK\r\n\r\n";
        int l = strlen(s);
        DistillerBufferAlloc(&hp->pxy_hdrs, 1+l);
        strcpy((char *)(hp->pxy_hdrs.data), s);
        DistillerBufferSetLength(&hp->pxy_hdrs,l);
      }
    }
  
    /*
   *  Replace the "Content-length" and "Content-type"
   *  headers with the correct info.  Leave other headers
   *  alone.
   */
    if (get_header_value(&hp->pxy_hdrs, "content-type", NULL,NULL,NULL) 
	== NULL) {
      insert_header(&hp->pxy_hdrs, "Content-type", dout.mimeType, 1);
    }
    
    if (get_header_value(&hp->pxy_hdrs,"content-length",NULL,NULL,NULL)
	== NULL) {
      char __tmp[12];
      snprintf(__tmp, 11, "%lu", DistillerBufferLength(&dout.data));
      insert_header(&hp->pxy_hdrs, "Content-length", __tmp, 1);
    }

    DistillerBufferClone(&hp->pxy_data, &dout.data);
  }

  if ((status == distOk) || (status == distRedispatch)) {
    DistillerBufferFree(&dout.data);
    DistillerBufferFree(&dout.metadata);
  }

  /* Always free this */
  DistillerBufferFree(&din.data);
  DistillerBufferFree(&din.metadata);
  
  /* BUG::must do Clib_Put here??? */
  return (retcode);
}
Example #16
0
File: rfc822.c Project: gpg/geam
int
rfc822_insert( RFC822 msg, char *line, size_t length )
{
    return msg->in_body? insert_body( msg, line, length )
           : insert_header( msg, line, length );
}