Beispiel #1
0
bool memcache_session::set_timeout(time_t ttl)
{
	const char* sid = get_sid();
	if (sid == NULL || * sid == 0)
		return false;

	return cache_->set(sid, ttl);
}
Beispiel #2
0
char *describe_streams (sockets *s, char *req, char *sbuf, int size)
{
	char *str, *stream_id;
	int i, sidf, do_play = 0, streams_enabled = 0;
	streams *sid;
	int do_all = 1;

	if (s->sid == -1 && strchr(req, '?'))
		setup_stream(req, s);

	sidf = get_session_id(s->sid);
	sid = get_sid(s->sid);
	if(sid)
		do_play = sid->do_play;
//	else LOG_AND_RETURN(NULL, "No session associated with sock_id %d", s->sock_id);
		
	snprintf(sbuf,size-1,"v=0\r\no=- %010d %010d IN IP4 %s\r\ns=SatIPServer:1 %d %d %d\r\nt=0 0\r\n", sidf, sidf, get_sock_host(s->sock), getS2Adapters(), getTAdapters(), getCAdapters() );
	if(strchr(req, '?'))
		do_all = 0;
		
	if((stream_id = strstr(req, "stream=")))
	{
		do_all = 0;
		sid = get_sid(map_int(stream_id + 7, NULL) - 1);
		if(sid == NULL)
			return NULL;		
	}	
	
	if(do_all)
	{
		for( i=0; i<MAX_STREAMS; i++)
			if(st[i].enabled)
			{
				int slen=strlen(sbuf);
				streams_enabled ++;
				snprintf(sbuf + slen, size - slen - 1, "m=video %d RTP/AVP 33\r\nc=IN IP4 0.0.0.0\r\na=control:stream=%d\r\na=fmtp:33 %s\r\na=%s\r\n", 
					ntohs (st[i].sa.sin_port), i+1, describe_adapter(i, st[i].adapter), st[i].do_play?"sendonly":"inactive");
				if( size - slen < 10)LOG_AND_RETURN(sbuf, "DESCRIBE BUFFER is full");
			}
	}else{
		int slen = strlen(sbuf);
		snprintf(sbuf + slen, size - slen - 1, "m=video 0 RTP/AVP 33\r\nc=IN IP4 0.0.0.0\r\na=control:stream=%d\r\na=fmtp:33 %s\r\nb=AS:5000\r\na=%s\r\n", 
			sid->sid + 1, describe_adapter(sid->sid, sid->adapter), do_play?"sendonly":"inactive");
	}
	return sbuf;
}
Beispiel #3
0
bool memcache_session::remove()
{
	const char* sid = get_sid();
	if (sid == NULL || * sid == 0)
		return false;

	return cache_->del(sid);
}
Beispiel #4
0
streams *
setup_stream (char *str, sockets * s)
{
	char *arg[20], pol;
	streams *sid;

	int i;
	transponder t;
	init_hw ();
	detect_dvb_parameters (str, &t);
	LOG ("Setup stream %d parameters, sock_id %d, handle %d", s->sid,
		s->id, s->sock);
	if (!get_sid(s->sid))				 // create the stream
	{
		int a_id = 0,
			s_id = 0;
		char pol;

		s_id = streams_add ();
		if(!(sid = get_sid(s_id)))
			LOG_AND_RETURN ( NULL, "Could not add a new stream");

		s->sid = s_id;
//		s->close_sec = 200;
//		s->timeout = (socket_action) stream_timeout;
		LOG ("Setup stream done: sid: %d (e:%d) for sock %d handle %d", s_id,
			st[s_id].enabled, s->id, s->sock);
	}
	if (!( sid = get_sid(s->sid)))
		LOG_AND_RETURN (NULL, "Stream %d not enabled for sock_id %d handle %d",
			s->sid, s->id, s->sock);
	
	set_stream_parameters (s->sid, &t);
	sid->do_play = 0;
	
	if(sid->adapter >= 0 && !strncasecmp( s->buf, "SETUP", 5 )) // SETUP after PLAY
	{
		int ad = sid->adapter;
		sid->adapter = -1;
		close_adapter_for_stream(sid->sid, ad);
	}
	
	return sid;
}
Beispiel #5
0
bool memcache_session::set_attrs(const std::map<string, session_string>& attrs)
{
	const char* sid = get_sid();
	if (sid == NULL || *sid == 0)
		return false;

	string buf;
	serialize(attrs, buf);  // 序列化数据
	time_t ttl = get_ttl();
	return cache_->set(sid, buf.c_str(), buf.length(), ttl);
}
Beispiel #6
0
static void sid_start(device_t *device, SIDTYPE sidtype)
{
	_SID6581 *sid = get_sid(device);
	const sid6581_interface *iface = (const sid6581_interface*) device->baseconfig().static_config();

	sid->device = device;
	sid->mixer_channel = device->machine->sound().stream_alloc(*device, 0, 1,  device->machine->sample_rate, (void *) sid, sid_update);
	sid->PCMfreq = device->machine->sample_rate;
	sid->clock = device->clock();
	sid->ad_read = iface ? iface->ad_read : NULL;
	sid->type = sidtype;

	sid6581_init(sid);
	sidInitWaveformTables(sidtype);
}
Beispiel #7
0
bool memcache_session::get_attrs(std::map<string, session_string>& attrs)
{
	// 清空原有数据
	attrs_clear(attrs);
	const char* sid = get_sid();
	if (sid == NULL || *sid == 0)
		return false;

	string buf;
	if (cache_->get(sid, buf) == false)
		return false;

	// 反序列化
	deserialize(buf, attrs);
	return true;
}
Beispiel #8
0
// we need to keep the pids from SETUP and PLAY into sid->tp
void
set_stream_parameters (int s_id, transponder * t)
{
	streams *sid;

	sid = get_sid(s_id);
	if (!sid || !sid->enabled)
		return;
	if (t->apids && t->apids[0] >= '0' && t->apids[0] <= '9')
	{
		strncpy (sid->apids, t->apids, LEN_PIDS);
		t->apids = sid->apids;
		sid->apids[LEN_PIDS] = 0;
	}
	if (t->dpids && t->dpids[0] >= '0' && t->dpids[0] <= '9')
	{
		strncpy (sid->dpids, t->dpids, LEN_PIDS);
		t->dpids = sid->dpids;
		sid->dpids[LEN_PIDS] = 0;
	}
	if (t->pids && t->pids[0] >= '0' && t->pids[0] <= '9')
	{
		strncpy (sid->pids, t->pids, LEN_PIDS);
		t->pids = sid->pids;
		sid->pids[LEN_PIDS] = 0;
	}
	
	if (t->x_pmt && t->x_pmt[0] >= '0' && t->x_pmt[0] <= '9')
	{
		strncpy (sid->x_pmt, t->x_pmt, LEN_PIDS);
		t->x_pmt = sid->x_pmt;
		sid->x_pmt[LEN_PIDS] = 0;
	}

	
	if (!t->apids)
		t->apids = sid->tp.apids;
	if (!t->dpids)
		t->dpids = sid->tp.dpids;
	if (!t->pids)
		t->pids = sid->tp.pids;
	if (!t->x_pmt)
		t->x_pmt = sid->tp.x_pmt;
		
		
	copy_dvb_parameters (t, &sid->tp);
}
Beispiel #9
0
static void sid_start(device_t *device, SIDTYPE sidtype)
{
	SID6581_t *sid = get_sid(device);
	const sid6581_interface *iface = (const sid6581_interface*) device->static_config();
	assert(iface);

	// resolve callbacks
	sid->in_potx_func.resolve(iface->in_potx_cb, *device);
	sid->in_poty_func.resolve(iface->in_poty_cb, *device);

	sid->device = device;
	sid->mixer_channel = device->machine().sound().stream_alloc(*device, 0, 1,  device->machine().sample_rate(), (void *) sid, sid_update);
	sid->PCMfreq = device->machine().sample_rate();
	sid->clock = device->clock();
	sid->type = sidtype;

	sid6581_init(sid);
	sidInitWaveformTables(sidtype);
}
Beispiel #10
0
static DEVICE_RESET( sid )
{
	_SID6581 *sid = get_sid(device);
	sidEmuReset(sid);
}
Beispiel #11
0
int
read_rtsp (sockets * s)
{
	char *arg[50];
	int cseq, la, i, rlen;
	char *proto, *transport = NULL, *useragent = NULL;
	int sess_id = 0;
	char buf[2000];
	streams *sid = get_sid(s->sid);

	if(s->buf[0]==0x24 && s->buf[1]<2)
	{
		if(sid)
			sid->rtime = s->rtime;

		int rtsp_len = s->buf[2]*256+s->buf[3];
		LOG("Received RTSP over tcp packet (sock_id %d, stream %d, rlen %d) packet len: %d, type %02X %02X discarding %s...", 
			s->id, s->sid, s->rlen, rtsp_len , s->buf[4], s->buf[5], (s->rlen == rtsp_len+4)?"complete":"fragment" );		
		if(s->rlen == rtsp_len+4){ // we did not receive the entire packet
			s->rlen = 0;			
			return 0;
		}
	}
	
	if (s->rlen < 4 || !end_of_header(s->buf + s->rlen - 4))
	{
		if( s->rlen > RBUF - 10 )
		{
			LOG("Discarding %d bytes from the socket buffer, request > %d, consider increasing  RBUF", s->rlen, RBUF);
			s->rlen = 0;
		}
		LOG("read_rtsp: read %d bytes from handle %d, sock_id %d, flags %d not ending with \\r\\n\\r\\n", s->rlen, s->sock, s->id, s->flags);
		if ( s->flags & 1 ) 
			return 0;		
		unsigned char *new_alloc = malloc1 (RBUF);
		memcpy(new_alloc, s->buf, s->rlen);
		s->buf = new_alloc;
		s->flags = s->flags | 1;
		return 0;
	}

	rlen = s->rlen;
	s->rlen = 0;

	LOG ("read RTSP (from handle %d sock_id %d, len: %d, sid %d):\n%s", s->sock, s->id, s->rlen, s->sid, s->buf);

	if( (s->type != TYPE_HTTP ) && (strncasecmp(s->buf, "GET", 3) == 0))
	{
		http_response (s , 404, NULL, NULL, 0, 0);
		return 0;
	}
	
	la = split (arg, s->buf, 50, ' ');
	cseq = 0;	
	if (la<2)
		LOG_AND_RETURN(0, "Most likely not an RTSP packet sock_id: %d sid: %d rlen: %d, dropping ....", s->id, s->sid, rlen); 
	
	if(s->sid<0)
		for (i = 0; i < la; i++)	
			if (strncasecmp ("Session:", arg[i], 8) == 0)
			{
				sess_id = map_int(header_parameter(arg, i), NULL);
				s->sid = find_session_id(sess_id);		
			}

	if(strstr(arg[1], "freq") || strstr(arg[1], "pids"))
	{
		int old_sid = s->sid;
		sid = (streams *) setup_stream (arg[1], s);
	}
	sid = get_sid(s->sid);
	if(sid)
		sid->rtime = s->rtime;

	if (sess_id)    
			set_session_id(s->sid, sess_id);
		
	
	for (i = 0; i < la; i++)
		if (strncasecmp ("CSeq:", arg[i], 5) == 0)
			cseq = map_int (header_parameter(arg, i), NULL);
		else if (strncasecmp ("Transport:", arg[i], 9) == 0){
			transport = header_parameter(arg, i);

			if( -1 == decode_transport (s, transport, opts.rrtp, opts.start_rtp))
			{
				http_response (s, 400, NULL, NULL, cseq, 0);
				return 0;
			}
		}
		else if (strstr (arg[i], "LIVE555"))
		{
			if(sid) sid->timeout = 0;
		}
		else if (strstr (arg[i], "Lavf"))
		{
			if(sid) sid->timeout = 0;
		}
		else if (strncasecmp ("User-Agent:", arg[i], 10) == 0)
			useragent = header_parameter(arg, i);
	
	if((strncasecmp (arg[0], "PLAY", 4) == 0) || (strncasecmp (arg[0], "GET", 3) == 0) || (strncasecmp (arg[0], "SETUP", 5) == 0)) 
	{
		char ra[100];
		int rv;
			
		if (!( sid = get_sid(s->sid)))
		{
			http_response (s, 454, NULL, NULL, cseq, 0);
			return 0;
		}

		if (useragent)
			strncpy(sid->useragent, useragent, 127);

		if ((strncasecmp (arg[0], "PLAY", 3) == 0) || (strncasecmp (arg[0], "GET", 3) == 0))
			if ((rv = start_play (sid, s)) < 0)
			{
				http_response (s, -rv , NULL, NULL, cseq, 0);
				return 0;
			}
		strcpy(ra, inet_ntoa (sid->sa.sin_addr));
		buf[0] = 0;
		if(transport)
		{
			int s_timeout = (sid->timeout ? sid->timeout : opts.timeout_sec) / 1000;
			switch (sid->type)
			{
				case STREAM_RTSP_UDP:
					if (atoi (ra) < 239)
						snprintf (buf, sizeof(buf), "Transport: RTP/AVP;unicast;destination=%s;source=%s;client_port=%d-%d;server_port=%d-%d\r\nSession: %010d;timeout=%d\r\ncom.ses.streamID: %d",
							ra, get_sock_host (s->sock), ntohs (sid->sa.sin_port), ntohs (sid->sa.sin_port) + 1,
//							opts.start_rtp, opts.start_rtp + 1, 
							get_sock_port(sid->rsock), get_sock_port(sid->rtcp),
							get_session_id (s->sid), s_timeout, sid->sid + 1);
					else
						snprintf (buf, sizeof(buf), "Transport: RTP/AVP;multicast;destination=%s;port=%d-%d\r\nSession: %010d;timeout=%d\r\ncom.ses.streamID: %d",
							ra, ntohs (sid->sa.sin_port), ntohs (sid->sa.sin_port) + 1,
							get_session_id (s->sid), s_timeout , sid->sid + 1);
					break;
				case STREAM_RTSP_TCP:
					snprintf(buf, sizeof(buf), "Transport: RTP/AVP/TCP;interleaved=0-1\r\nSession: %010d;timeout=%d\r\ncom.ses.streamID: %d", 
						get_session_id (s->sid), s_timeout, sid->sid + 1);
					break;
			}
		}
		
		if (strncasecmp(arg[0], "PLAY", 4) == 0)
		{
			char *qm = strchr(arg[1], '?');
			if(qm)
				*qm = 0;
			if(buf[0])
				strcat(buf, "\r\n");
			
			snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf) - 1,  "RTP-Info: url=%s;seq=%d;rtptime=%lld\r\nRange: npt=0.000-", arg[1], getTick(),(long long int)(getTickUs()/1000000));
		}
		if(buf[0]==0 && sid->type == STREAM_HTTP)
				snprintf(buf, sizeof(buf), "Content-Type: video/mp2t");
		http_response (s, 200, buf, NULL, cseq, 0);
	}
	else if (strncmp (arg[0], "TEARDOWN", 8) == 0)
	{
		streams *sid;
		buf[0] = 0;
		if(get_sid(s->sid))
			sprintf(buf, "Session: %010d", get_session_id(s->sid));
		close_stream (s->sid);		
		http_response (s, 200, buf, NULL, cseq, 0);
	}
	else
	{
		if (strncmp (arg[0], "DESCRIBE", 8) == 0)
		{
			char sbuf[1000];
			char *rv = NULL;
			rv = describe_streams(s, arg[1], sbuf, sizeof(sbuf));
			if (! rv)
			{
				http_response (s, 404, NULL, NULL, cseq, 0);
				return 0;
			}	
			snprintf(buf, sizeof(buf), "Content-type: application/sdp\r\nContent-Base: rtsp://%s/", get_sock_host(s->sock));
			http_response (s, 200, buf, sbuf, cseq, 0);
				
		}
		else if (strncmp (arg[0], "OPTIONS", 8) == 0)
		{
			http_response (s, 200, public, NULL, cseq, 0);
		}
	}
//------------------------------------------------------------------------------
//génération de profil DACL pour modifier les droits !!
BOOL create_sd_from_list( SECURITY_DESCRIPTOR *sdout, int num, ...)
{
  va_list ap;
  SID **sids = 0;
  char *name;
  DWORD amask;
  DWORD acl_size;
  PACL pacl = 0;
  int i;
  if((sids = (SID **)calloc(1,sizeof(SID *)*num)) == 0)return FALSE;

  acl_size = num * (sizeof(ACL) +
             sizeof(ACCESS_ALLOWED_ACE) +
             sizeof(DWORD));

  /* Collect all the SID's */
  va_start( ap, num);
  for( i = 0; i < num; i++) {
    name = va_arg( ap, char *);
    amask = va_arg(ap, DWORD);
    if(get_sid( name, &sids[i]) == FALSE)goto cleanup;

    acl_size += GetLengthSid(sids[i]);
  }
  va_end(ap);

  if((pacl = (PACL)LocalAlloc( LMEM_FIXED, acl_size)) == 0)goto cleanup;
  if(InitializeSecurityDescriptor( sdout, SECURITY_DESCRIPTOR_REVISION) == FALSE)goto cleanup;
  if(InitializeAcl( pacl, acl_size, ACL_REVISION) == FALSE)goto cleanup;

  va_start(ap, num);
  for( i = 0; i < num; i++) {
    ACE_HEADER *ace_p;
    name = va_arg( ap, char *);
    amask = va_arg( ap, DWORD);
    if(AddAccessAllowedAce( pacl, ACL_REVISION, amask, sids[i]) == FALSE)goto cleanup;

    /* Make sure the ACE is inheritable */
    if(GetAce( pacl, 0, (LPVOID *)&ace_p) == FALSE)goto cleanup;

    ace_p->AceFlags |= ( CONTAINER_INHERIT_ACE | OBJECT_INHERIT_ACE);
  }

  /* Add the ACL into the sd. */
  if(SetSecurityDescriptorDacl( sdout, TRUE, pacl, FALSE) == FALSE)goto cleanup;

  for( i = 0; i < num; i++)
    if(sids[i] != 0)
      LocalFree((HLOCAL)sids[i]);
  free(sids);

  return TRUE;

cleanup:

  if(sids != 0) {
    for( i = 0; i < num; i++)
      if(sids[i] != 0)
        LocalFree((HLOCAL)sids[i]);
    free(sids);
  }
  if(pacl != 0)
    LocalFree((HLOCAL)pacl);
  return FALSE;
}
Beispiel #13
0
int decode_transport (sockets * s, char *arg, char *default_rtp, int start_rtp)
{
	char *arg2[10];
	int l;
	rtp_prop p;
	streams *sid = get_sid(s->sid);
	if (! sid)
	{
		LOG("Error: No stream to set transport to, sock_id %d, arg %s ",s->id, arg);
		return -1;
	}
	l = 0;
	sid->rsock_err = 0;
	if ( arg )
	{
		if (strstr(arg, "RTP/AVP/TCP"))
		{
			LOG("Assuming RTSP over TCP for stream %d, arg %s", sid->sid, arg);
			sid->type = STREAM_RTSP_TCP;
			sid->rsock = s->sock;
			return 0;
		}
		
		l = split (arg2, arg, 10, ';');
	
	}
	//      LOG("arg2 %s %s %s",arg2[0],arg2[1],arg2[2]);
	memset (&p, 0, sizeof (p));
	while (l > 0)
	{
		l--;
		if (strcmp ("multicast", arg2[l]) == 0)
			p.type = TYPE_MCAST;
		if (strcmp ("unicast", arg2[l]) == 0)
			p.type = TYPE_UNICAST;
		if (strncmp ("ttl=", arg2[l], 4) == 0)
			p.ttl = atoi (arg2[l] + 4);
		if (strncmp ("client_port=", arg2[l], 12) == 0)
			p.port = atoi (arg2[l] + 12);
		if (strncmp ("port=", arg2[l], 5) == 0)
			p.port = atoi (arg2[l] + 5);
		if (strncmp ("destination=", arg2[l], 12) == 0)
			strncpy (p.dest, arg2[l] + 12, sizeof (p.dest));
	}
	if (default_rtp)
		strncpy (p.dest, default_rtp, sizeof (p.dest));
	if (p.dest[0] == 0 && p.type == TYPE_UNICAST)
		strncpy (p.dest, inet_ntoa (s->sa.sin_addr), sizeof (p.dest));
	if (p.dest[0] == 0)
		strcpy (p.dest, opts.disc_host);
	if (p.port == 0)
		p.port = start_rtp;
	LOG ("decode_transport ->type %d, ttl %d new socket to: %s:%d", p.type, p.ttl, p.dest, p.port);
	if( sid->type != 0)
	{
		if(sid->type == STREAM_RTSP_UDP && sid->rsock >= 0)			
		{
			int oldport = ntohs(sid->sa.sin_port);
			char *oldhost = inet_ntoa(sid->sa.sin_addr);
			
			if(p.port == oldport && !strcmp(p.dest,oldhost))
				LOG("Transport for this connection is already setup to %s:%d, leaving as it is: sid = %d, handle %d", 
					p.dest, p.port, sid->sid, sid->rsock)
			else {
				LOG("Stream has already a transport header associated with it to %s:%d - sid = %d type = %d, closing %d", 
					oldhost, oldport, sid->sid, sid->type, sid->rsock);
				close(sid->rsock);
				sid->rsock = -1;
				sid->type = 0;
			}
		}
	}
Beispiel #14
0
/* Process TCP packets
 * Return 0 to accept packet, otherwise to drop packet 
 */
int process_tcp_packet(struct mypacket *packet, char inout)
{
    int ret = 0;
    struct myiphdr *iphdr = packet->iphdr;
    struct mytcphdr *tcphdr = packet->tcphdr;
    unsigned char *payload = packet->payload;

    char sip[16], dip[16];
    ip2str(iphdr->saddr, sip);
    ip2str(iphdr->daddr, dip);

    unsigned short sport, dport;
    //unsigned int seq, ack;
    sport = ntohs(tcphdr->th_sport);
    dport = ntohs(tcphdr->th_dport);
    //seq = tcphdr->th_seq;
    //ack = tcphdr->th_ack;
    log_debug("[TCP] This packet goes from %s:%d to %s:%d", sip, sport, dip, dport);
    log_debug("TCP flags: %s", tcp_flags(tcphdr->th_flags));

    struct fourtuple fourtp;
    fourtp.saddr = iphdr->saddr;
    fourtp.daddr = iphdr->daddr;
    fourtp.sport = tcphdr->th_sport;
    fourtp.dport = tcphdr->th_dport;

    // for testing uni-directional packet forwarding to bypass IP blocking 
    //if (dport == 80 && is_blocked_ip(dip)) {
    //    log_debug("Going to forward that packet!!!");
    //    unsigned int newlen = packet->len + 4;
    //    char *newpkt = (char*)malloc(newlen);
    //    memcpy(newpkt, packet->data, packet->len);
    //    *(u_int32_t*)(newpkt + packet->len) = iphdr->daddr;
    //    ip_hdr(newpkt)->daddr = str2ip(PACKET_FORWARDER);
    //    send_raw(newpkt, newlen);
    //    log_debug("sent!!!");
    //    return 0;
    //}

    if (tcphdr->th_flags == TCP_SYN) {
        // Processing outgoing SYN packet. 

        // Uploading diagnostic log is disabled. (2017.9.1) 
        //if (strcmp(dip, FEEDBACK_SERVER_IP) == 0)
        //    return 0;
        

        // choose a strategy for the newly created connection
        int sid = choose_strategy_by_historical_result(iphdr->daddr);
        log_debug("Using strategy %s", g_strats[sid].name);
        set_sid(&fourtp, sid);
        //cache_strategy(&fourtp, sid);

        if (g_strats[sid].process_syn) {
            ret = g_strats[sid].process_syn(packet);
#ifndef EVALUATION
            if (ret) {
                need_evaluation(&fourtp);
            }
#endif
        }
    }
    if (tcphdr->th_flags == (TCP_SYN | TCP_ACK)) {
        // Got a SYN-ACK from server

        // send an ACK with 1 TTL to make home router happy 
        if (opt_inject_ack_with_one_ttl)
            send_ACK_with_one_ttl(dip, dport, sip, sport, tcphdr->th_ack, htonl(ntohl(tcphdr->th_seq)+1));

        struct fourtuple reverse_fourtp;
        reverse_fourtp.saddr = iphdr->daddr;
        reverse_fourtp.daddr = iphdr->saddr;
        reverse_fourtp.sport = tcphdr->th_dport;
        reverse_fourtp.dport = tcphdr->th_sport;

        int sid = get_sid(&reverse_fourtp);
        if (sid >= 0) {
            if (get_ttl(iphdr->saddr) == 0) {
                // if TTL hasn't been initialized 
                // find initial TTL from SYN/ACK packet
                int ttl = choose_appropriate_ttl(iphdr->ttl);
                set_ttl(iphdr->saddr, ttl);
            }
            if  (g_strats[sid].process_synack) {
                ret = g_strats[sid].process_synack(packet);
#ifndef EVALUATION
                if (ret) {
                    need_evaluation(&reverse_fourtp);
                }
#endif
            }
        }
        else if (sid == -1) {
            ret = process_synack_for_ttl_probing(packet);
        }

        //if (opt_inject_syn_and_syn_ack_with_one_ttl)
        //    send_one_ttl_SYN_and_SYN_ACK(dip, dport, sip, sport, tcphdr->th_ack, tcphdr->th_seq);
    } 
    else if ((tcphdr->th_flags & TCP_ACK) && 
        !(tcphdr->th_flags & (TCP_SYN | TCP_RST))) {
        // ignore ACK packets without payload 
        if (packet->payload_len == 0) 
            return 0;

        if (dport == 80) {
            if ((payload[0] == 'G' && payload[1] == 'E' && 
                 payload[2] == 'T' && payload[3] == ' ') ||
                (payload[0] == 'P' && payload[1] == 'O' && 
                 payload[2] == 'S' && payload[3] == 'T' && 
                 payload[4] == ' ')) {
                // Got a outgoing HTTP request 
                log_debug("[TCP] Sent a HTTP request from %s:%d to %s:%d.", sip, sport, dip, dport);
                int i, j, k, l;
                
                //char req_line[1000];
                //for (i = 0; i < 1000; i++) {
                //    if (payload[i] == '\r' || payload[i] == '\n') {
                //        req_line[i] = 0;
                //        break;
                //    }
                //    req_line[i] = payload[i];
                //}
                
                // Generate the HTTP request line. Format: GET/POST domain/url. e.g. GET www.google.com/index.php
                char req_line2[1000];
                // copy GET/POST 
                for (i = 0; payload[i] != ' ' && i < packet->payload_len; i++) {
                    req_line2[i] = payload[i];
                }
                req_line2[i++] = ' ';
                k = i; 
    
                // find Host field
                for (j = i; j < packet->payload_len; j++) {
                    if (payload[j] == 'H' && payload[j+1] == 'o' &&
                            payload[j+2] == 's' && payload[j+3] == 't' &&
                            payload[j+4] == ':' && (payload[j-1] == '\r' || payload[j-1] == '\n')) {
                        j += 5;
                        // copy Host value 
                        while (payload[j] == ' ') j++;
                        for (l = 0; l < 99 && j+l < packet->payload_len; l++) {
                            if (payload[j+l] == '\r' || payload[j+l] == '\n')
                                break;
                            req_line2[k++] = payload[j+l];
                        }
                        break;
                    }
                }

                // copy the rest of request line 
                for (; i < 900 && i < packet->payload_len; i++) {
                    if (payload[i] == '\r' || payload[i] == '\n') {
                        break;
                    }
                    req_line2[k++] = payload[i];
                }
                req_line2[k] = 0;
    
                log_debug("[TCP] %s", req_line2); 

                int sid = get_sid(&fourtp);
                if (sid >= 0 && g_strats[sid].process_request) {
                    ret = g_strats[sid].process_request(packet);
#ifndef EVALUATION
                    if (ret) {
                        need_evaluation(&fourtp);
                    }
#endif
                }
#ifdef EVALUATION
                if (strstr(req_line2, "ultrasurf") || strstr(req_line2, "goodword")) {
                    need_evaluation(&fourtp);
                }
#endif

                cache_http_request(&fourtp, req_line2);
            }
        }
        else if (sport == 80) {
            if (payload[0] == 'H' && payload[1] == 'T' && payload[2] == 'T' && payload[3] == 'P') {
                // Got a incoming HTTP response 
                log_debug("[TCP] Got a HTTP response from %s:%d to %s:%d.", sip, sport, dip, dport);
                process_http_response(&fourtp, tcphdr->th_seq, iphdr->ttl);
            }
        }
        else if (dport == 53) {
            // Got a DNS request over TCP 
            log_debug("[TCP] Sent a DNS request from %s:%d to %s:%d.", sip, sport, dip, dport);

            int sid = get_sid(&fourtp);
            if (sid >= 0 && g_strats[sid].process_request) {
                ret = g_strats[sid].process_request(packet);
#ifndef EVALUATION
                if (ret) {
                    need_evaluation(&fourtp);
                }
#endif
            }

            cache_dns_tcp_request(&fourtp);
        }
        else if (sport == 53) {
            // Got a DNS response over TCP, maybe triggered by our app, or maybe not 
            log_debug("[TCP] Got a DNS response from %s:%d to %s:%d.", sip, sport, dip, dport);
            // parse the DNS response to get the first qname 
            const unsigned char *dns_payload = packet->payload + 2;
            struct mydnshdr *dnshdr = (struct mydnshdr*)dns_payload;
            unsigned short txn_id = htons(dnshdr->txn_id);
            int qdcount = ntohs(dnshdr->questions);
            char qname[MAX_QNAME_LEN];
            if (qdcount > 0) {
                //log_debug("Questions: %d", qdcount);
                unsigned char *ptr = (unsigned char *)(dnshdr + 1);
                {
                    struct mydnsquery query;
                    int j = 0, l;
                    while (1) {
                        for (l = *ptr++; l != 0; l--) {
                            query.qname[j++] = *ptr++;
                            if (j >= MAX_QNAME_LEN) {
                                while (*ptr != 0) ptr++;
                                break;
                            }
                        }
                        if (*ptr == 0) {
                            query.qname[j] = 0;
                            ptr++;
                            break;
                        }
                        query.qname[j++] = '.';
                    }
                    query.qtype = (ptr[0] << 8) + ptr[1];
                    query.qclass = (ptr[2] << 8) + ptr[3];
                    
                    log_debug("DNS Query: %s %d %d", query.qname, query.qtype, query.qclass);
    
                    // use the first query to calc hash 
                    qname[0] = 0;
                    strncat(qname, query.qname, MAX_QNAME_LEN - 1);
                }

                // Tell the caching thread to process the dns udp response
                // use DNS transaction ID and first query name as unique ID
                // transaction ID alone may cause collision 
                process_dns_tcp_response(txn_id, qname, &fourtp, tcphdr->th_seq, iphdr->ttl, packet->payload, packet->payload_len);

            }
        }
        else if (dport == opt_vpn_port) {
            // outgoing packet
            int sid = get_sid(&fourtp);
            if (sid >= 0 && g_strats[sid].process_request) {
                ret = g_strats[sid].process_request(packet);
                if (ret) {
                    if (opt_inject_syn_and_syn_ack_with_one_ttl == 1)
                        send_one_ttl_SYN(sip, sport, dip, dport, tcphdr->th_seq);
                    else if (opt_inject_syn_and_syn_ack_with_one_ttl == 2)
                        send_one_ttl_SYN_and_SYN_ACK(sip, sport, dip, dport, tcphdr->th_seq, tcphdr->th_ack);
                }
            }
        }
        else if (sport == opt_vpn_port) {
            // incomine packet
        }
        else if (dport == opt_tor_port) {
            // outgoing packet
            int sid = get_sid(&fourtp);
            if (sid >= 0 && g_strats[sid].process_request) {
                ret = g_strats[sid].process_request(packet);
                if (ret) {
                    if (opt_inject_syn_and_syn_ack_with_one_ttl == 1)
                        send_one_ttl_SYN(sip, sport, dip, dport, tcphdr->th_seq);
                    else if (opt_inject_syn_and_syn_ack_with_one_ttl == 2)
                        send_one_ttl_SYN_and_SYN_ACK(sip, sport, dip, dport, tcphdr->th_seq, tcphdr->th_ack);
                }
            }
        }
        else if (sport == opt_tor_port) {
            // incomine packet
        }
        else {
            // TODO: for all other protocols. This branch is a piece of temporary code, should be re-write.
            if (inout == 0) {
                // incoming packet
                log_debug("this is an incoming packet.");
            }
            else {
                // outgoing packet
                log_debug("this is an outgoing packet.");
                int sid = get_sid(&fourtp);
                if (sid >= 0 && g_strats[sid].process_request) {
                    ret = g_strats[sid].process_request(packet);
                    if (ret) {
                        if (opt_inject_syn_and_syn_ack_with_one_ttl == 1)
                            send_one_ttl_SYN(sip, sport, dip, dport, tcphdr->th_seq);
                        else if (opt_inject_syn_and_syn_ack_with_one_ttl == 2)
                            send_one_ttl_SYN_and_SYN_ACK(sip, sport, dip, dport, tcphdr->th_seq, tcphdr->th_ack);
                    }
                }
            }
        }
    }
    else if (tcphdr->th_flags & TCP_RST) {
        // Got an incoming RST 
        log_debug("[TCP] Got an incoming RST from %s:%d to %s:%d.", sip, sport, dip, dport);

        process_incoming_RST(packet);
    }

    return ret;
}