示例#1
0
文件: server.c 项目: macrobit/FTP
void child(int index, struct sockaddr_in* ptr_connaddr, struct datagram* ptr_conn_gram) {
    struct datagram recv_gram;
    struct datagram send_gram;
    struct datagram* sendbuf;
    uint32_t* sendtv;
    char *tmp;
    int sockfd;
    int nready;
    int i;
    fd_set rset, allset;
    int maxfdp1 = 0;
    struct sockaddr_in servaddr, cliaddr;
    int local = 0;
    int on = 1;
    int len;
    //int filepos = -1;
    int filesize = 0;
    int servsockclosed = 0;
    int recv_seq;
    int last_ack;
    int last_ack_times;
    int recv_ack;
    int send_seq;
    int send_flag;
    int seq = 2568;
    int newport = 0;
    int recv_lock = 0;
    int eof = 0;
    int send_exist = 0;
    int buf_to_send = 0;
    int ssth = 0;
    float congestion_size = 1;
    int max_size = 0;
    uint32_t ts;
    FILE* file;
    char* payload;
    char* filename;
    struct rtt_info rttinfo;

    rtt_init(&rttinfo);
    for (i=0;i<count;i++) {
        if (i != index) {
            Close(sockfds[i]);
            continue;
        }
    }

    // todo: file not exist
    // todo: pipeline
    payload = get_payload_ptr(ptr_conn_gram);
    recv_windowsize = *(int*)payload;
    filename = payload+sizeof(int);

    printf("Client [%s:%d] request %s\n", inet_ntoa(ptr_connaddr->sin_addr), ntohs(ptr_connaddr->sin_port), filename);

    file = fopen(filename, "r");
    if (!file) {
        printf("File not exist: %s\n", filename);
        Close(sockfd);
        return;
    }

    fseek(file, 0, SEEK_END);
    filesize = ftell(file);
    fseek(file, 0, SEEK_SET);

    local = is_local(addrs[index], ptr_connaddr, 0);

    sockfd = Socket(AF_INET, SOCK_DGRAM, 0);
    Setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on));

    bzero(&servaddr, sizeof(servaddr));
    servaddr.sin_family      = AF_INET;
    servaddr.sin_addr.s_addr = ((struct sockaddr_in*)addrs[index]->ifi_addr)->sin_addr.s_addr;
    servaddr.sin_port        = 0;

    Bind(sockfd, (SA *) &servaddr, sizeof(servaddr));

    len = sizeof(servaddr);
    getsockname(sockfd, (SA *) &servaddr, &len);

    if (local == 0) {
        printf("Client [%s:%d] is not LOCAL\n", inet_ntoa(ptr_connaddr->sin_addr), ntohs(ptr_connaddr->sin_port));
    } else if (local == 1) {
        printf("Client [%s:%d] is LOCAL\n", inet_ntoa(ptr_connaddr->sin_addr), ntohs(ptr_connaddr->sin_port));
    } else if (local == 2) {
        printf("Client [%s:%d] is LOOPBACK\n", inet_ntoa(ptr_connaddr->sin_addr), ntohs(ptr_connaddr->sin_port));
    }

    if (local)
        Setsockopt(sockfd, SOL_SOCKET, SO_DONTROUTE, &on, sizeof(on));

    //Connect(sockfd, (SA*)ptr_connaddr, sizeof(struct sockaddr_in));

    // init
    // todo: fail
    sendbuf = (struct datagram*)malloc(windowsize*sizeof(struct datagram));
    memset(sendbuf, 0, windowsize*sizeof(struct datagram));
    sendtv = (uint32_t*)malloc(windowsize*sizeof(uint32_t));
    memset(sendtv, 0, windowsize*sizeof(uint32_t));
    send_exist = 0;
    last_ack = 0;
    last_ack_times = 0;

    newport = (int)ntohs(servaddr.sin_port);
    printf("New port for client [%s:%d] is %d\n", inet_ntoa(ptr_connaddr->sin_addr), ntohs(ptr_connaddr->sin_port), newport);

    get_header(ptr_conn_gram, 0, &recv_seq, 0, &ts);
    make_datagram(&sendbuf[0], SYN | ACK, seq, recv_seq+1, ts, (char*)&newport, sizeof(newport));
    sendtv[0] = rtt_ts(&rttinfo) + rtt_start(&rttinfo);
    send_to(sockfd, &sendbuf[0], ptr_connaddr, sizeof(struct sockaddr_in));
    send_exist++;

    FD_ZERO(&allset);
    FD_ZERO(&rset);
    FD_SET(sockfd, &allset);
    maxfdp1 = sockfd+1;

    for(;;) {
        rset = allset;
        // handle timeout
        // todo: rtt, recv_lock
        ts = rtt_start(&rttinfo);
        struct timeval tv;
        tv.tv_sec = ts/1000;
        tv.tv_usec = (ts % 1000)*1000;

        nready = select(maxfdp1, &rset, NULL, NULL, &tv);
        if (nready < 0) {
            if (errno == EINTR)
                continue;       /* back to for() */
            else
                err_sys("select error");
        } else if (nready == 0) {
            // timeout
            if (recv_lock) {
                ts = rtt_ts(&rttinfo);
                make_datagram(&send_gram, ACK, 0, 0, ts, NULL, 0);
                send_to(sockfd, &send_gram, ptr_connaddr, sizeof(*ptr_connaddr));
                continue;
            }

            // resend
            for (i=0;i<windowsize;i++) {
                if (0 == sendtv[i])
                    continue;

                ts = rtt_ts(&rttinfo);
                if (ts >= sendtv[i]) {
                    set_ts(&sendbuf[i], ts);
                    send_to(sockfd, &sendbuf[i], ptr_connaddr, sizeof(*ptr_connaddr));
                    sendtv[i] = ts + rtt_start(&rttinfo);
                }
            }

            if (rtt_timeout(&rttinfo) < 0) {
                if (!servsockclosed) {
                    Close(sockfds[index]);
                    servsockclosed = 1;
                }

                Close(sockfd);
                fclose(file);

                printf("Too many timeouts for Client [%s:%d]\n", inet_ntoa(ptr_connaddr->sin_addr), ntohs(ptr_connaddr->sin_port));
                return;
            }

            ssth = (int)congestion_size/2;
            if (ssth < 1)
                ssth = 1;
            congestion_size = 1;
            printf("Timeout slow start\n");
            continue;
        }

        if (FD_ISSET(sockfd, &rset)) {
            len = sizeof(cliaddr);
            recv_from(sockfd, &recv_gram, &cliaddr, &len);
            get_header(&recv_gram, 0, 0, &recv_ack, &ts);
            rtt_stop(&rttinfo, rtt_ts(&rttinfo)-ts);

            payload = get_payload_ptr(&recv_gram);
            recv_lock = (*(int*)payload == 0)?1:0; 

            if (!servsockclosed) {
                Close(sockfds[index]);
                servsockclosed = 1;
            }
            
            for (i=0;i<windowsize;i++) {
                get_header(&sendbuf[i], &send_flag, &send_seq, 0, 0);
                if (!send_flag)
                    continue;
                
                if (send_seq < recv_ack) {
                    set_flag(&sendbuf[i], 0);
                    sendtv[i] = 0;
                    send_exist--;
                }
            }

            if ((recv_ack > seq) && eof) {
                Close(sockfd);
                fclose(file);

                printf("Client [%s:%d] end\n", inet_ntoa(ptr_connaddr->sin_addr), ntohs(ptr_connaddr->sin_port));
                return;
            }

            if (last_ack == recv_ack) {
                last_ack_times++;
            } else {
                last_ack = recv_ack;
                last_ack_times=1;
            }

            if (last_ack_times >= 3) {
                last_ack = 0;
                for (i=0;i<windowsize;i++) {
                    get_header(&sendbuf[i], &send_flag, &send_seq, 0, 0);
                    if (!send_flag)
                        continue;

                    if (send_seq == recv_ack)
                        break;
                }
                
                ts = rtt_ts(&rttinfo);
                set_ts(&sendbuf[i], ts);
                send_to(sockfd, &sendbuf[i], ptr_connaddr, sizeof(*ptr_connaddr));
                // todo: congestion
                printf("Fast recvory\n");
                congestion_size = ssth;
                if (congestion_size <= 0)
                    congestion_size = 1;

                continue;
            }

            // todo: congestion
            max_size = windowsize;
            if (recv_windowsize < max_size)
                max_size = recv_windowsize;

            if (congestion_size < ssth) {
                congestion_size++;
                if (congestion_size >= ssth) {
                    printf("Reach slow start threshold\n");
                }
            } else {
                congestion_size += (max_size > 0)? 1.0/max_size:1.0;
            }

            if (congestion_size < max_size)
                max_size = (int)congestion_size;

            if (eof || recv_lock) {
                buf_to_send = 0;
            } else if (send_exist < max_size) {
                buf_to_send = max_size - send_exist;
            } else if (send_exist >= max_size) {
                buf_to_send = 0;
            }

            //printf("buf_to_send %d\n", buf_to_send);
            for (;buf_to_send > 0;buf_to_send--) {
                for (i=0;i<windowsize;i++) {
                    get_header(&sendbuf[i], &send_flag, &send_seq, 0, 0);
                    if (!send_flag)
                        break;
                }

                seq++;
                ts = rtt_ts(&rttinfo);
                make_datagram(&sendbuf[i], DAT, seq, 0, ts, NULL, 0);
                payload = get_payload_ptr(&sendbuf[i]);
                //len = fread(payload+4, BUFFER_SIZE-HEADER_SIZE-4, 1, file);
                len = fread(payload+4, 1, BUFFER_SIZE-HEADER_SIZE-4, file);
                *(int*)payload = len;
                //printf("f %d %s\n", len, payload+4);
                if (ftell(file) >= filesize) {
                    eof = 1;
                    set_fin_flag(&sendbuf[i]);
                }

                sendtv[i] = ts + rtt_start(&rttinfo);
                send_to(sockfd, &sendbuf[i], ptr_connaddr, sizeof(*ptr_connaddr));
                send_exist++;

                if (eof)
                    break;
            }
        }
    }
}
// the kernel bootstrap routine
PUBLIC
void 
kernel_thread_t::bootstrap()
{
  // Initializations done -- helping_lock_t can now use helping lock
  helping_lock_t::threading_system_active = true;

  //
  // set up my own thread control block
  //
  state_change (0, Thread_running);

  sched()->set_prio (config::kernel_prio);
  sched()->set_mcp (config::kernel_mcp);
  sched()->set_timeslice (config::default_time_slice);
  sched()->set_ticks_left (config::default_time_slice);

  present_next = present_prev = this;
  ready_next = ready_prev = this;

  //
  // set up class variables
  //
  for (int i = 0; i < 256; i++) prio_next[i] = prio_first[i] = 0;
  prio_next[config::kernel_prio] = prio_first[config::kernel_prio] = this;
  prio_highest = config::kernel_prio;

  timeslice_ticks_left = config::default_time_slice;
  timeslice_owner = this;

  // 
  // install our slow trap handler
  //
  nested_trap_handler = base_trap_handler;
  base_trap_handler = thread_handle_trap;

  // 
  // initialize FPU
  // 
  set_ts();			// FPU ops -> exception

  //
  // initialize interrupts
  //
  irq_t::lookup(2)->alloc(this, false); // reserve cascade irq
  irq_t::lookup(8)->alloc(this, false); // reserve timer irq

  pic_enable_irq(2);		// allow cascaded irqs

  // set up serial console
  if (! strstr(kmem::cmdline(), " -I-") 
      && !strstr(kmem::cmdline(), " -irqcom"))
    {
      int com_port = console::serial_com_port;
      int com_irq = com_port & 1 ? 4 : 3;

      irq_t::lookup(com_irq)->alloc(this, false); // the remote-gdb interrupt
      pic_enable_irq(com_irq);

      // for some reason, we have to re-enable the com irq here
      if (config::serial_esc)
	com_cons_enable_receive_interrupt();
    }

  // initialize the profiling timer
  bool user_irq0 = strstr(kmem::cmdline(), "irq0");

  if (config::profiling)
    {
      if (user_irq0)
	{
	  kdb_ke("options `-profile' and `-irq0' don't mix "
		  "-- disabling `-irq0'");
	}
      irq_t::lookup(0)->alloc(this, false);

      profile::init();

      if (strstr(kmem::cmdline(), " -profstart"))
	profile::start();
    }
  else if (! user_irq0)
    irq_t::lookup(0)->alloc(this, false); // reserve irq0 even though
                                          // we don't use it

  // 
  // set up timer interrupt (~ 1ms)
  //
  while (rtcin(RTC_STATUSA) & RTCSA_TUP) ; // wait till RTC ready
  rtcout(RTC_STATUSA, RTCSA_DIVIDER | RTCSA_1024); // 1024 Hz
  // set up 1024 Hz interrupt
  rtcout(RTC_STATUSB, rtcin(RTC_STATUSB) | RTCSB_PINTR | RTCSB_SQWE); 
  rtcin(RTC_INTR);		// reset

  pic_enable_irq(8);		// allow this interrupt

  //
  // set PCE-Flag in CR4 to enable read of performace measurement counters
  // in usermode. PMC were introduced in Pentium MMX and PPro processors.
  //
  #ifndef CPUF_MMX
  #define CPUF_MMX 0x00800000
  #endif
  if(strncmp(cpu.vendor_id, "GenuineIntel", 12) == 0
     && (cpu.family == CPU_FAMILY_PENTIUM_PRO ||
	 cpu.feature_flags & CPUF_MMX))
    {
      set_cr4(get_cr4() | CR4_PCE);
    }
  
  //
  // allow the boot task to create more tasks
  //
  for (unsigned i = config::boot_taskno + 1; 
       i < space_index_t::max_space_number;
       i++)
    {
      check(space_index_t(i).set_chief(space_index(), 
				       space_index_t(config::boot_taskno)));
    }

  //
  // create sigma0
  //

  // sigma0's chief is the boot task
  space_index_t(config::sigma0_id.id.task).
    set_chief(space_index(), space_index_t(config::sigma0_id.id.chief));

  sigma0 = new space_t(config::sigma0_id.id.task);
  sigma0_thread = 
    new (&config::sigma0_id) thread_t (sigma0, &config::sigma0_id, 
				       config::sigma0_prio, 
				       config::sigma0_mcp);
  
  // push address of kernel info page to sigma0's stack
  vm_offset_t esp = kmem::info()->sigma0_esp;

  * reinterpret_cast<vm_offset_t*>(kmem::phys_to_virt(--esp)) 
    = kmem::virt_to_phys(kmem::info());

  sigma0_thread->initialize(kmem::info()->sigma0_eip, esp,
			    0, 0);

  //
  // create the boot task
  //

  // the boot task's chief is the boot task itself
  space_index_t(config::boot_id.id.task).
    set_chief(space_index(), space_index_t(config::boot_id.id.chief));

  space_t *boot = new space_t(config::boot_id.id.task);
  thread_t *boot_thread
    = new (&config::boot_id) thread_t (boot, &config::boot_id, 
				       config::boot_prio, 
				       config::boot_mcp);

  boot_thread->initialize(0x200000,
			  0x200000,
			  sigma0_thread, 0);

  //
  // the idle loop
  //
  for (;;) 
    {
      // printf("I");

      sti();			// enable irqs, otherwise idling is fatal

      if (config::hlt_works_ok)
	asm("hlt");		// stop the CPU, waiting for an int

      while (ready_next != this) // are there any other threads ready?
	schedule();
    }
}
示例#3
0
文件: Thread.c 项目: Fluray/MollenOS
/* Task Switch occurs here */
Registers_t *_ThreadingSwitch(Registers_t *Regs, int PreEmptive, uint32_t *TimeSlice, 
							 uint32_t *TaskPriority)
{
	/* We'll need these */
	Cpu_t Cpu;
	MCoreThread_t *mThread;
	x86Thread_t *tx86;

	/* Sanity */
	if (ThreadingIsEnabled() != 1)
		return Regs;

	/* Get CPU */
	Cpu = ApicGetCpu();

	/* Get thread */
	mThread = ThreadingGetCurrentThread(Cpu);

	/* What the f**k?? */
	assert(mThread != NULL && Regs != NULL);

	/* Cast */
	tx86 = (x86Thread_t*)mThread->ThreadData;

	/* Save FPU/MMX/SSE State */
	if (tx86->Flags & X86_THREAD_USEDFPU)
		save_fpu(tx86->FpuBuffer);

	/* Save stack */
	if (mThread->Flags & THREADING_USERMODE)
		tx86->UserContext = Regs;
	else
		tx86->Context = Regs;

	/* Switch */
	mThread = ThreadingSwitch(Cpu, mThread, (uint8_t)PreEmptive);
	tx86 = (x86Thread_t*)mThread->ThreadData;

	/* Update user variables */
	*TimeSlice = mThread->TimeSlice;
	*TaskPriority = mThread->Priority;

	/* Update Addressing Space */
	MmVirtualSwitchPageDirectory(Cpu, 
		(PageDirectory_t*)mThread->AddrSpace->PageDirectory, mThread->AddrSpace->Cr3);

	/* Set TSS */
	TssUpdateStack(Cpu, (Addr_t)tx86->Context);

	/* Finish Transition */
	if (mThread->Flags & THREADING_TRANSITION)
	{
		mThread->Flags &= ~THREADING_TRANSITION;
		mThread->Flags |= THREADING_USERMODE;
	}

	/* Clear FPU/MMX/SSE */
	tx86->Flags &= ~X86_THREAD_USEDFPU;

	/* Set TS bit in CR0 */
	set_ts();

	/* Return new stack */
	if (mThread->Flags & THREADING_USERMODE)
		return tx86->UserContext;
	else
		return tx86->Context;
}