Example #1
0
void Ctransaction::recv()
{
	const int cb_b = 2 << 10;
	char b[cb_b];
	while (1)
	{
		socklen_t cb_a = sizeof(sockaddr_in);
		int r = m_s.recvfrom(mutable_data_ref(b, cb_b), reinterpret_cast<sockaddr*>(&m_a), &cb_a);
		if (r == SOCKET_ERROR)
		{
			if (WSAGetLastError() != WSAEWOULDBLOCK)
				std::cerr << "recv failed: " << Csocket::error2a(WSAGetLastError()) << std::endl;
			return;
		}
		if (r < uti_size)
			return;
		switch (read_int(4, b + uti_action, b + r))
		{
		case uta_connect:
			if (r >= utic_size)
				send_connect(data_ref(b, r));
			break;
		case uta_announce:
			if (r >= utia_size)
				send_announce(data_ref(b, r));
			break;
		case uta_scrape:
			if (r >= utis_size)
				send_scrape(data_ref(b, r));
			break;
		}
	}
}
Example #2
0
int process_client_request (int sock_s,  char *line, int total_line_num, int is_ms_server)
{
   unsigned int nleft;
   int nwrite;
   char *ptrWrite, *ptrTemp, writeBuf[MAX_BUFFER_SIZE];
   char responseBuf[MAX_LINE_NUMBER][256];
   int i, next_line_num;
   rtsp_method_t method = UNKNOWN;
   int CSeq;
   int CL_line_num = 0;

   nleft = 0;
   nwrite = 0;
    
   bzero(responseBuf, sizeof(char) * MAX_LINE_NUMBER*256);
   printf("\nprocess_client_request(): \n");
   for (i=0; i< total_line_num; i++)
   {
       //printf("rcvd line[%d]= %s", i,line);
       if ( i == 0 ) { /* the first line in the request */ 
           if (strstr(line, "SETUP") >0 ) {
                 method = SETUP;
                 printf("\tmethod = SETUP\n");
           } else  if ( strstr(line, "PLAY") > 0 ) {
                 method = PLAY;
                 printf("\tmethod = PLAY\n");
           } else if ( strstr(line, "TEARDOWN") > 0 ) {
                 method = TEARDOWN;
                 printf("\tmethod = TEARDOWN\n");
           } else if ( strstr(line, "DESCRIBE") > 0 ) {
                 method = DESCRIBE;
                 printf("\tmethod = DESCRIBE\n");
           } else if ( strstr(line, "GET_PARAMETER") >0 ) {
                 method = GET_PARAMETER;
                 printf("\tmethod = GET_PARAMETER\n");
           } else if ( strstr(line, "PAUSE") > 0 ) {
                 method = PAUSE;
                 printf("\tmethod = PAUSE\n");
           } else if ( strstr(line, "200 OK") >0 ) {
                 method = ANNOUNCE_REPLY;
                 printf("\tmethod = ANNOUNCE_REPLY");
           } else {
                 method = UNKNOWN;
                 //printf("\tmethod = UNKNOWN\n");
           }

         
       } /* done with the fisrt line */
       else 
       { /*the rest lines */ 
           if ( strstr(line, "Content-Length") > 0 )   /* skip the conten-Length, we need to add 
                                                           Content_Lenght according to how many 
                                                           bytes we send out*/
           {
              CL_line_num =i; //will be used for Get_parameter later
           }
           else   //has no Content-Length
           {
 
              if (( strstr(line, "Range:") > 0 ) && (sub_choice == PLAY_NO_RANGE_HEADER))
              {
                /* for testing when no Range: hdr is not include in PLAY response */
                //do not copy teh line
              }
              else
              {
                 strcpy(responseBuf[i], line);
              }
           }


           if (strstr(line, "CSeq") > 0)
           {
              CSeq = cseq_parser(line);
              //printf("\n CSeq is %d\n", CSeq); 
           }

       } /*done the rest lines*/        

       line= line +256; /* move to next line */      

   } /* done for loop */

   next_line_num =i;

   /*printf("total lines: next_line_num=%d\n", next_line_num);*/

   /* build response msg */

   switch (method)
   {
     case SETUP:
         if (sub_choice == SETUP_ERROR)
         {
            strcpy(responseBuf[0], "RTSP/1.0 404 NOT FOUND\r\n");
            strcpy(responseBuf[next_line_num],"\r\n");
    
           break;
         }
        
         /* NORMAL case: 200 OK */ 

//         if (menu_choice != ONE_MS_SERVER_AND_ONE_VOD_SERVER)
//         {
//         strcpy(responseBuf[0], "RTSP/1.0 200 OK\r\n");
//         strcpy(responseBuf[next_line_num++], "Session: 4050682558055376826\r\n");
//         }
//         else// (menu_choice == ONE_MS_SERVER_AND_ONE_VOD_SERVER)
//         {
            next_line_num = 0;
            strcpy(responseBuf[next_line_num++], "RTSP/1.0 200 OK\r\n");
            strcpy(responseBuf[next_line_num++], "CSeq: 1\r\n");
            if (sub_choice == SETUP_HAS_TIMEOUT_VALUE_RETURNED)
              strcpy(responseBuf[next_line_num++], "Session: 5059691751022412168;timeout=60\r\n");
            else
              strcpy(responseBuf[next_line_num++], "Session: 5059691751022412168\r\n");


            if (menu_choice == ONE_MS_SERVER_AND_ONE_VOD_SERVER)
            {
                  strcpy(responseBuf[next_line_num++], "ControlSession: 8888691751022412168\r\n");
                  strcpy(responseBuf[next_line_num++], location_hdr);
            }

            if (vod_stream_transport_type == 1 ) //VOD_over IP
            {
               sprintf(responseBuf[next_line_num++], "StreamAddress: %s:%d\r\n", vod_server_ip_addr,VOD_SERVER_PORT);
            }
            else
            {
               sprintf(responseBuf[next_line_num++], "Tuning: frequency=11570\r\n");
            }
            strcpy(responseBuf[next_line_num++], "Channel: Tsid=3;Svcid=12\r\n");
 //        }
            
         strcpy(responseBuf[next_line_num],"\r\n");
       break;

     case PLAY:
         if (sub_choice == PLAY_ERROR)
         {
            strcpy(responseBuf[0], "RTSP/1.0 400 Bad Request\r\n");
            strcpy(responseBuf[next_line_num],"\r\n");
            break;
         }
        
         /* NORMAL case: 200 OK */ 
         strcpy(responseBuf[0], "RTSP/1.0 200 OK\r\n");

       break;
    
     case PAUSE:
         /* NORMAL case: 200 OK */ 
         strcpy(responseBuf[0], "RTSP/1.0 200 OK\r\n");
       break;


     case DESCRIBE:
         if (sub_choice == DESCRIBE_ERROR)
         {
            strcpy(responseBuf[0], "RTSP/1.0 400 Bad Request\r\n");
            strcpy(responseBuf[next_line_num],"\r\n");
            break;
         }
        
         /* NORMAL case: 200 OK */ 
         strcpy(responseBuf[0], "RTSP/1.0 200 OK\r\n");
         
         if (menu_choice != ONE_MS_SERVER_AND_ONE_VOD_SERVER)
         {

            strcpy(responseBuf[next_line_num++],"Date: Tue, 02 May 2006  00:02:31 GMT\r\n");
            strcpy(responseBuf[next_line_num++],"Content-Length: 236\r\n");
            strcpy(responseBuf[next_line_num++],"\r\n");
            strcpy(responseBuf[next_line_num++],"v=0\r\n");
            strcpy(responseBuf[next_line_num++],"o=- 1146528151955250 9727864823646 IN IP4 192.168.0.102\r\n");
            strcpy(responseBuf[next_line_num++],"s=RTSP Session\r\n");
            strcpy(responseBuf[next_line_num++],"t=0 0\r\n");
            strcpy(responseBuf[next_line_num++],"i=\r\n");
            strcpy(responseBuf[next_line_num++],"b=AS:4837\r\n");
            strcpy(responseBuf[next_line_num++],"a=type:vod\r\n");
            strcpy(responseBuf[next_line_num++],"a=range:npt=0-91.052\r\n");
            strcpy(responseBuf[next_line_num++],"c=IN IP4 0.0.0.0\r\n");
            strcpy(responseBuf[next_line_num++],"a=control:rtsp://192.168.0.241/vanhelsing.mpi\r\n");
            strcpy(responseBuf[next_line_num++],"m=video 0 RTP/AVP 33\r\n");
            strcpy(responseBuf[next_line_num++],"a=framerate:25.00\r\n"); 
            strcpy(responseBuf[next_line_num],"\r\n");
         }
         else
         {
            strcpy(responseBuf[next_line_num++],"Content-Type: application/sdp\r\n");
            strcpy(responseBuf[next_line_num++],"Content-Length: 41\r\n");
            strcpy(responseBuf[next_line_num++],"\r\n");
            strcpy(responseBuf[next_line_num++],"i=\r\n");
            strcpy(responseBuf[next_line_num++],"a=type:vod\r\n");
            strcpy(responseBuf[next_line_num++],"a=range:npt=0-139.234\r\n");
            strcpy(responseBuf[next_line_num],"\r\n");
         }
       break;

     case TEARDOWN:
         strcpy(responseBuf[0], "RTSP/1.0 200 OK\r\n");
         strcpy(responseBuf[next_line_num],"\r\n");
       break;
   
     case GET_PARAMETER:
         if (sub_choice == GET_PARAMETER_ERROR)
         {
            strcpy(responseBuf[0], "RTSP/1.0 400 Bad Request\r\n");
            strcpy(responseBuf[next_line_num],"\r\n");
            break;
         }
        
         /* NORMAL case: 200 OK */ 
         strcpy(responseBuf[0], "RTSP/1.0 200 OK\r\n");

         if (CL_line_num >0 )
         {
           next_line_num = CL_line_num;
           if ((menu_choice == ONE_MS_SERVER_AND_ONE_VOD_SERVER))
           {
              if ((is_ms_server == 0) /* VOD server */ ||
                  (sub_choice == GET_PARAMETER_ALWAYS_SEND_MSG_BODY))
              {
                 strcpy(responseBuf[next_line_num++],"Content-Length: 53\r\n");
                 strcpy(responseBuf[next_line_num++],"\r\n");
                 strcpy(responseBuf[next_line_num++],"stream_state: playing\r\n");
                 strcpy(responseBuf[next_line_num++],"position: 92.99\r\n");
                 strcpy(responseBuf[next_line_num++],"Scale: 1.5\r\n");
                 strcpy(responseBuf[next_line_num],"\r\n");
              }
              else /* ms server */
              {
                 strcpy(responseBuf[next_line_num],"\r\n");
              }
           }
           else
           {
              strcpy(responseBuf[next_line_num++],"Content-Length: 53\r\n");
              strcpy(responseBuf[next_line_num++],"\r\n");
              strcpy(responseBuf[next_line_num++],"stream_state: playing\r\n");
              strcpy(responseBuf[next_line_num++],"position: 92.99\r\n");
              strcpy(responseBuf[next_line_num++],"Scale: 2.5\r\n");
              strcpy(responseBuf[next_line_num],"\r\n");
           }
         }
       
       break;

     case ANNOUNCE_REPLY:
     case UNKNOWN:
     default: 
       break;
    } /*end of switch (method) */

   if (method == ANNOUNCE_REPLY  )
   {
     return 0;
   }

   /* printf("total next_line_num=%d\n", next_line_num);*/

   for (i=0; i<= next_line_num; i++)
   {
     printf("\tresponseBuf[%d]=%s", i, responseBuf[i]);
   }

   if (method == UNKNOWN )
   {
     return 0;
   }


   ptrWrite = writeBuf;

   bzero( ptrWrite, MAX_BUFFER_SIZE);

   ptrTemp= ptrWrite;

   for (i=0; i< next_line_num ; i++)
   {
       nleft = strlen( responseBuf[i]);
       /*printf("i=%d, nleft=%d\n", i, nleft);*/
       strncpy(ptrTemp, responseBuf[i], nleft);
       ptrTemp +=  nleft;

    } /*end of for */

    *ptrTemp= '\r';
    ptrTemp++;
    *ptrTemp= '\n';

    nleft= ptrTemp - ptrWrite + 1;

    while (nleft >0) {
          //printf("nleft=%d\n",  nleft);
      if ( (nwrite = write (sock_s, ptrWrite, nleft)) < 0 ) {
        if (errno == EINTR)
            nwrite = 0; /* call write again */
        else
                {
                        printf("ERROR in  write. i=%d\n",i);
                return (-1);
                }
       } /* end if */
       nleft -= nwrite;
       ptrWrite += nwrite;
     } /* end of while (nleft) */

    printf("sent the response, CSeq=%d\n\n", CSeq);

    if ((sub_choice == ANNOUNCE_EVENT_CODE_OK) || ( sub_choice == ANNOUNCE_EVENT_CODE_ERROR))
    {
       if ( CSeq == 6 )
       {
           printf( "send a announce\n");
           send_announce( sock_s);
       }     
       return 0;
    }

    return 0;
}
Example #3
0
/**
 * Perform the Announce/Register phase for a particular group/file
 * Group & encryption: ->ANNOUNCE <-REGISTER ->KEYINFO <-INFO_ACK
 * Group & no encryption: ->ANNOUNCE <-REGISTER ->REG_CONF
 * Files within a group: ->FILEINFO <-INFO_ACK
 * If client_key == 1, REGISTER is followed by CLIENT_KEY
 * Returns 1 if at least one client responded, 0 if none responded
 */
int announce_phase(struct finfo_t *finfo)
{
    time_t endtime;
    int attempt, resend, announce, regconf, keyinfo, fileinfo, open, anyerror;
    int len, rval, rcv_status, last_pass, gotall, gotone, allreg, regdone, i;
    unsigned char *packet, *decrypted;
    struct uftp_h *header;
    struct timeval timeout;
    struct sockaddr_in receiver;

    if (finfo->file_id) {
        log1(0, 0, "File ID: %04X  Name: %s", finfo->file_id, finfo->filename);
        log1(0, 0, "  sending as: %s", finfo->destfname);
        switch (finfo->ftype) {
        case FTYPE_REG:
            log(0, 0, "Bytes: %s  Blocks: %d  Sections: %d", 
                       printll(finfo->size), finfo->blocks, finfo->sections);
            break;
        case FTYPE_DIR:
            log(0, 0, "Empty directory");
            break;
        case FTYPE_LINK:
            log(0, 0, "Symbolic link to %s", finfo->linkname);
            break;
        }
    } else {
        log(0, 0, "Initializing group");
        if (sync_mode) {
            log0(0, 0, "- Connect -");
        }
    }

    rval = 1;
    packet = calloc(mtu, 1);
    decrypted = calloc(mtu, 1);
    if ((packet == NULL) || (decrypted == NULL)) {
        syserror(0, 0, "calloc failed!");
        exit(1);
    }
    header = (struct uftp_h *)packet;
    endtime = time(NULL) + announce_time;
    announce = (finfo->file_id == 0);
    regconf = (announce && (keytype == KEY_NONE));
    keyinfo = (announce && (keytype != KEY_NONE));
    fileinfo = (finfo->file_id != 0);
    open = (destcount == 0);
    for (i = 0; i < destcount; i++) {
        // At start of group, initialize all clients/proxies to DEST_MUTE.
        // At start of file, initialize proxies to DEST_ACTIVE (since they
        // don't respond directly to a FILEINFO) and clients to DEST_REGISTERED.
        if (announce) {
            destlist[i].status = DEST_MUTE;
        } else if (!client_error(i)) {
            if (destlist[i].clientcnt != -1) {
                destlist[i].status = DEST_ACTIVE;
            } else {
                destlist[i].status = DEST_REGISTERED;
            }
        }
    }

    timeout.tv_sec = announce_int / 1000;
    timeout.tv_usec = (announce_int % 1000) * 1000;
    resend = 1;
    attempt = 1;
    last_pass = 0;
    regdone = 0;
    while (time(NULL) < endtime) {
        // On the initial pass, or when the announce timeout trips,
        // send any necessary messages.
        if (resend) {
            if (keyinfo && !send_keyinfo(finfo, attempt)) {
                continue;
            }
            if (announce && !send_regconf(finfo, attempt, regconf)) {
                continue;
            }
            if (fileinfo && !send_fileinfo(finfo, attempt)) {
                continue;
            }
            if (announce && !send_announce(finfo, attempt, open)) {
                continue;
            }
            resend = 0;
        }
        // TODO: Currently, the interval between sends is really an inactivity
        // timer, not the actual time between sends.  We might want to change
        // it to that, and perhaps add an extra "overage" timer in case we're
        // still processing responses when we're due to resend, that way we'll
        // always wait some minimum amount of time.
        if ((rcv_status = read_packet(sock, &receiver, packet, &len,
                                      mtu, &timeout)) == -1) {
            continue;
        } else if (rcv_status == 0) {
            attempt++;
            resend = 1;
            if (last_pass) break;
            continue;
        }
        if (!validate_packet(packet, len, finfo)) {
            continue;
        }

        if (!handle_announce_phase(packet, decrypted, &receiver, finfo,
                                   announce, open, regconf)) {
            continue;
        }
        if (!open) {
            for (i = 0, gotall = 1, allreg = 1;
                    (i < destcount) && (gotall || allreg); i++) {
                if (announce) {
                    gotall = gotall && ((destlist[i].status == DEST_ACTIVE) ||
                                        (destlist[i].status == DEST_ABORT));
                    allreg = allreg && ((destlist[i].status == DEST_ACTIVE) ||
                                (destlist[i].status == DEST_REGISTERED) ||
                                (destlist[i].status == DEST_ABORT));
                } else {
                    gotall = gotall && ((destlist[i].status == DEST_ACTIVE) ||
                                        (destlist[i].status == DEST_DONE) ||
                                        (client_error(i)));
                }
            }
            if (gotall) {
                // Break out right away if this is a file registration.
                // For group registration, do one last wait, even if 
                // encryption is enabled since we can still send a
                // REG_CONF for a client behind a proxy.
                // Change the wait interval to the client's register_int * 1.5
                // to allow for late registers.
                // Be careful not to overrun the phase timeout!
                if (finfo->file_id != 0) break;
                timeout.tv_sec = (int)(register_int / 1000 * 1.5);
                timeout.tv_usec = (int)((register_int % 1000) * 1000 * 1.5);
                if (timeout.tv_sec > endtime) {
#ifdef WINDOWS
                    timeout.tv_sec = (long)endtime;
#else
                    timeout.tv_sec = endtime;
#endif
                    timeout.tv_usec = 0;
                }
                if (!last_pass) {
                    log(0, 0, "Late registers:");
                }
                last_pass = 1;
                send_regconf(finfo, attempt + 1, regconf);
            } else if (announce && allreg && !regdone) {
                // All have registered, so don't wait to send the next message
                resend = 1;
                regdone = 1;
            }
        }
    }
    for (i = 0, gotone = 0, anyerror = 0; i < destcount; i++) {
        gotone = gotone || (((destlist[i].status == DEST_ACTIVE) || 
                             (destlist[i].status == DEST_DONE)) && 
                            (destlist[i].clientcnt == -1));
        if (destlist[i].status == DEST_REGISTERED) {
            log1(0, 0, "Couldn't get INFO_ACK from %s", destlist[i].name);
            destlist[i].status = DEST_LOST;
            anyerror = 1;
        }
        if ((destlist[i].status == DEST_MUTE) ||
                (destlist[i].status == DEST_ABORT)) {
            anyerror = 1;
        }
    }
    if (anyerror && quit_on_error) {
        log0(0, 0, "Aboring all clients");
        send_abort(finfo, "A client dropped out, aborting all",
                &receive_dest, NULL, (keytype != KEY_NONE), 0);
        for (i = 0; i < destcount; i++) {
            if (destlist[i].status == DEST_ACTIVE) {
                destlist[i].status = DEST_ABORT;
            }
        }
        rval = 0;
    }
    if (!gotone) {
        log0(0, 0, "Announce timed out");
        rval = 0;
    }
    if (open) {
        send_regconf(finfo, attempt, regconf);
    }
    if ((finfo->file_id == 0) && sync_mode) {
        for (i = 0; i < destcount; i++) {
            if (destlist[i].status == DEST_ACTIVE) {
                log0(0, 0, "CONNECT;success;%s", destlist[i].name);
            } else {
                log0(0, 0, "CONNECT;failed;%s", destlist[i].name);
            }
        }
        log0(0, 0, "- Transfer -");
    }
    free(packet);
    free(decrypted);
    return rval;
}