示例#1
0
TEST_F(RingBuf, RingBufRW2_1)
{
    RingBuf_t   ringbuf;
    uint8_t     wbuf[3];
    uint8_t     rbuf[3];
    size_t      sz;

    for (int i = 0; i < 3; i++) {
        RingBufAlloc(&ringbuf, 3);
        ringbuf.wpos = i;        //ずらす
        ringbuf.rpos = (ringbuf.wpos + 1) % 3;
        memset(ringbuf.buf, 0xdd, 3);
        ringbuf.empty = false;

        //1回ずつ書いて、1回ずつ読む

        //書ける
        wbuf[0] = 0x12;
        sz = 1;
        RingBufWrite(&ringbuf, wbuf, &sz);
        ASSERT_EQ(1UL, sz);

        //書けない
        wbuf[0] = 0x78;
        sz = 1;
        RingBufWrite(&ringbuf, wbuf, &sz);
        ASSERT_EQ(0UL, sz);

        //読める
        sz = 1;
        RingBufRead(&ringbuf, rbuf, &sz);
        ASSERT_EQ(1UL, sz);
        ASSERT_EQ(0xdd, rbuf[0]);

        //読める
        sz = 1;
        RingBufRead(&ringbuf, rbuf, &sz);
        ASSERT_EQ(1UL, sz);
        ASSERT_EQ(0xdd, rbuf[0]);

        //読める
        sz = 1;
        RingBufRead(&ringbuf, rbuf, &sz);
        ASSERT_EQ(1UL, sz);
        ASSERT_EQ(0x12, rbuf[0]);

        //読めない
        sz = 1;
        RingBufRead(&ringbuf, rbuf, &sz);
        ASSERT_EQ(0UL, sz);

        RingBufFree(&ringbuf);
    }
}
示例#2
0
TEST_F(RingBuf, RingBufRW1_2)
{
    RingBuf_t   ringbuf;
    uint8_t     wbuf[3];
    uint8_t     rbuf[5];
    size_t      sz;

    for (int i = 0; i < 3; i++) {
        RingBufAlloc(&ringbuf, 3);
        ringbuf.rpos = ringbuf.wpos = i;        //ずらす

        //2回で書いて、1回で読む

        //書ける
        wbuf[0] = 0x12;
        wbuf[1] = 0x34;
        sz = 2;
        RingBufWrite(&ringbuf, wbuf, &sz);
        ASSERT_EQ(2UL, sz);

        //書ける
        wbuf[0] = 0x56;
        wbuf[1] = 0x78;
        sz = 2;
        RingBufWrite(&ringbuf, wbuf, &sz);
        ASSERT_EQ(1UL, sz);

        //書けない
        wbuf[0] = 0x78;
        sz = 1;
        RingBufWrite(&ringbuf, wbuf, &sz);
        ASSERT_EQ(0UL, sz);

        //読める
        sz = 5;
        RingBufRead(&ringbuf, rbuf, &sz);
        ASSERT_EQ(3UL, sz);
        ASSERT_EQ(0x12, rbuf[0]);
        ASSERT_EQ(0x34, rbuf[1]);
        ASSERT_EQ(0x56, rbuf[2]);

        //読めない
        sz = 1;
        RingBufRead(&ringbuf, rbuf, &sz);
        ASSERT_EQ(0UL, sz);

        RingBufFree(&ringbuf);
    }
}
示例#3
0
//RingBufRead_{rpos}_{wpos}_{sz}
TEST_F(RingBuf2, RingBufRead2_2_2)
{
    //書込みデータ
    //     !empty
    //      +---+
    //   RW2| 3 |
    //     1| 2 |
    //     0| 1 |
    //      +---+
    RingBuf2::mBuf.rpos = 2;
    RingBuf2::mBuf.wpos = 2;
    RingBuf2::mBuf.empty = false;
    RingBuf2::mBuf.buf[0] = 1;
    RingBuf2::mBuf.buf[1] = 2;
    RingBuf2::mBuf.buf[2] = 3;


    uint8_t data[3];
    memset(data, 0xdd, sizeof(data));
    size_t sz = 2;

    RingBufRead(&RingBuf2::mBuf, data, &sz);

    //下エリア用のバッファが足りないパターン
    ASSERT_EQ(1, RingBuf2::mBuf.rpos);
    ASSERT_EQ(2, RingBuf2::mBuf.wpos);
    ASSERT_EQ(2UL, sz);
    ASSERT_EQ(3, data[0]);
    ASSERT_EQ(1, data[1]);
    ASSERT_EQ(0xdd, data[2]);
    ASSERT_FALSE(RingBuf2::mBuf.empty);
}
示例#4
0
//RingBufRead_{rpos}_{wpos}_{sz}
TEST_F(RingBuf2, RingBufRead2_0_3)
{
    //書込みデータ
    //     !empty
    //      +---+
    //    R2| 3 |
    //     1| 2 |
    //    W0| 1 |
    //      +---+
    RingBuf2::mBuf.rpos = 2;
    RingBuf2::mBuf.wpos = 0;
    RingBuf2::mBuf.empty = false;
    RingBuf2::mBuf.buf[0] = 1;
    RingBuf2::mBuf.buf[1] = 2;
    RingBuf2::mBuf.buf[2] = 3;


    uint8_t data[3];
    memset(data, 0xdd, sizeof(data));
    size_t sz = 3;

    RingBufRead(&RingBuf2::mBuf, data, &sz);

    ASSERT_EQ(0, RingBuf2::mBuf.rpos);
    ASSERT_EQ(0, RingBuf2::mBuf.wpos);
    ASSERT_EQ(1UL, sz);
    ASSERT_EQ(3, data[0]);
    ASSERT_EQ(0xdd, data[1]);
    ASSERT_EQ(0xdd, data[2]);
    ASSERT_TRUE(RingBuf2::mBuf.empty);
}
示例#5
0
//RingBufRead_{rpos}_{wpos}_{sz}
TEST_F(RingBuf2, RingBufRead0_0_2)
{
    //書込みデータ
    //     !empty
    //      +---+
    //     2| 3 |
    //     1| 2 |
    //   RW0| 1 |
    //      +---+
    RingBuf2::mBuf.rpos = 0;
    RingBuf2::mBuf.wpos = 0;
    RingBuf2::mBuf.empty = false;
    RingBuf2::mBuf.buf[0] = 1;
    RingBuf2::mBuf.buf[1] = 2;
    RingBuf2::mBuf.buf[2] = 3;


    uint8_t data[3];
    memset(data, 0xdd, sizeof(data));
    size_t sz = 2;

    RingBufRead(&RingBuf2::mBuf, data, &sz);

    ASSERT_EQ(2, RingBuf2::mBuf.rpos);
    ASSERT_EQ(0, RingBuf2::mBuf.wpos);
    ASSERT_EQ(2UL, sz);
    ASSERT_EQ(1, data[0]);
    ASSERT_EQ(2, data[1]);
    ASSERT_FALSE(RingBuf2::mBuf.empty);
}
示例#6
0
TEST_F(RingBuf2, RingBufRead_empty)
{
    //書込みデータ無し
    //      empty
    //      +---+
    //     2|   |
    //     1|   |
    //   RW0|   |
    //      +---+


    uint8_t data[5];
    memset(data, 0xdd, sizeof(data));
    size_t sz = sizeof(data);

    RingBufRead(&RingBuf2::mBuf, data, &sz);

    ASSERT_EQ(0, RingBuf2::mBuf.rpos);
    ASSERT_EQ(0, RingBuf2::mBuf.wpos);
    ASSERT_TRUE(RingBuf2::mBuf.empty);
    ASSERT_EQ(0UL, sz);
    for (int i = 0; i < (int)sizeof(data); i++) {
        ASSERT_EQ(0xdd, data[i]);
    }
}
示例#7
0
unsigned vdd_read(BYTE* p, unsigned count)
{
	sem_wait(rdbuf.sem);
	count=RingBufRead(&rdbuf,p,count);
	if(count==0)
		lprintf(LOG_ERR,"!VDD_READ: RingBufRead read 0");

	return(count);
}
示例#8
0
//---------------------------------------------------------------------------
void __fastcall TSpyForm::SpyTimerTick(TObject *Sender)
{
    uchar   buf[1024];
    int     rd;

    if(*outbuf==NULL)
        return;

    rd=RingBufRead(*outbuf,buf,sizeof(buf)-1);
    if(rd) {
        rd=strip_telnet(buf,rd);
        Terminal->WriteBuffer(buf,rd);
        Timer->Interval=1;
    } else
        Timer->Interval=250;
}
示例#9
0
//*****************************************************************************
//
// This function is called in the context of the main loop to process any
// touch screen messages that have been sent.  Messages are posted to a
// queue from the message handler and pulled off here.  This is required
// since it is not safe to have two different execution contexts performing
// graphics operations using the same graphics context.
//
//*****************************************************************************
void
ProcessTouchMessages(void)
{
    tScribbleMessage sMsg;

    //
    // Loop while there are more messages to process.
    //
    while(!RingBufEmpty(&g_sMsgQueue)) {
        //
        // Get the next message.
        //
        RingBufRead(&g_sMsgQueue, (uint8_t *)&sMsg, sizeof(tScribbleMessage));

        //
        // Dispatch it to the handler.
        //
        TSMainHandler(sMsg.ui32Msg, sMsg.i32X, sMsg.i32Y);
    }
}
示例#10
0
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
BOOL SBBSExecInt16::handler(VMHANDLE hVM, CLIENT_STRUCT* pRegs, DWORD intno)
{
	BYTE 	ch;
    DWORD   avail;
	vm_t*	vm = find_vm(hVM);

	if(vm==NULL || !(vm->mode&SBBSEXEC_MODE_DOS_IN)) {
		return(FALSE); // Tells VMM that interrupt was not handled
	}

//    DBTRACExx(0,"Int16 (hVM, AX)", hVM, _clientAX);

	avail=RingBufFull(&vm->in);
 	switch(_clientAH) {
    	case 0x00:	// Read char from keyboard
        case 0x10:	// Read char from enhanced keyboard
			if(avail) {
	            RingBufRead(&vm->in, &ch, 1);
				_clientAX=ch;
				return(TRUE);
			}
			break;
    	case 0x01:	// Get keyboard status
        case 0x11:	// Get enhanced keyboard status
			if(avail) {
                RingBufPeek(&vm->in, &ch, 1);
                _clientFlags&=~(1<<6);	// clear zero flag
                _clientAX=ch;
				return(TRUE);
    	    }
	        break;
        default:
		    DBTRACEx(0,"!UNHANDLED INT16 function", _clientAH);
            break;
	}

    return(FALSE);
}
示例#11
0
DWORD SBBSExec::OnW32DeviceIoControl(PIOCTLPARAMS pIOCTL)
{
	DWORD	rd;
	DWORD	wr;
	DWORD	avail;
	vm_t*	vm;

//	DBTRACEd(0,"SBBSEXEC ioctl"
		//,pIOCTL->dioc_IOCtlCode);

	switch(pIOCTL->dioc_IOCtlCode) {
		case DIOC_OPEN:
			DBTRACEd(0,"IOCTL: OPEN",Get_System_Time());
			break;

		case DIOC_CLOSEHANDLE:
			DBTRACEd(0,"IOCTL: CLOSE",Get_System_Time());
			break;

		case SBBSEXEC_IOCTL_START:
			DBTRACEd(0,"IOCTL: START",Get_System_Time());
			DBTRACEx(0,"Current Thread Handle",Get_Cur_Thread_Handle());
			if(start.event) {
				DBTRACE(0,"Exec already started!");
				return(SBBSEXEC_ERROR_INUSE);
			}
			if (pIOCTL->dioc_InBuf==NULL 
				|| pIOCTL->dioc_cbInBuf!=sizeof(start)) {
				return(SBBSEXEC_ERROR_INBUF);
			}
			start=*(sbbsexec_start_t*)pIOCTL->dioc_InBuf;
			break;

		case SBBSEXEC_IOCTL_COMPLETE:
			DBTRACEd(0,"IOCTL: COMPLETE",Get_System_Time());
			if(start.event || new_vm==NULL) {
				DBTRACE(0,"!VM never created");
				start.event=0;
				return(SBBSEXEC_ERROR_INUSE);
			}
			if(pIOCTL->dioc_OutBuf==NULL
				|| pIOCTL->dioc_cbOutBuf<sizeof(VMHANDLE)) {
				DBTRACE(0,"!Invalid OUTBUF");
				return(SBBSEXEC_ERROR_OUTBUF);
			}
			*(VMHANDLE*)pIOCTL->dioc_OutBuf=new_vm->handle;
			DBTRACEx(0,"CREATED VM HANDLE", new_vm->handle);
			new_vm=NULL;

			if(pIOCTL->dioc_bytesret!=NULL)
				*pIOCTL->dioc_bytesret = sizeof(VMHANDLE);
			break;
		case SBBSEXEC_IOCTL_READ:

			if (pIOCTL->dioc_InBuf==NULL
				|| pIOCTL->dioc_cbInBuf!=sizeof(VMHANDLE)) {
				DBTRACE(0,"!INVALID INBUF");
				return(SBBSEXEC_ERROR_INBUF);
			}

			if (pIOCTL->dioc_OutBuf==NULL || pIOCTL->dioc_cbOutBuf==0) {
				DBTRACE(0,"!INVALID OUTBUF");
				return(SBBSEXEC_ERROR_OUTBUF);
			}

			vm = find_vm(*(VMHANDLE*)pIOCTL->dioc_InBuf);
			if(vm==NULL) {
				DBTRACE(0,"!NO VM LIST");
				return(SBBSEXEC_ERROR_INDATA);
			}

			rd = RingBufFull(&vm->out);

			if(rd>pIOCTL->dioc_cbOutBuf) {
				DBTRACEdd(0,"Reducing read size"
                	,rd, pIOCTL->dioc_cbOutBuf);
				rd=pIOCTL->dioc_cbOutBuf;
			}

			RingBufRead(&vm->out, (BYTE*)pIOCTL->dioc_OutBuf, rd);

			if(pIOCTL->dioc_bytesret!=NULL)
				*pIOCTL->dioc_bytesret = rd;

            if(vm->output_sem!=NULL) // Wake up int14 handler
            	Signal_Semaphore(vm->output_sem);

            if(rd>1) {
            	DBTRACEd(1,"IOCTL_READ bytes", rd);
            }
			break;

		case SBBSEXEC_IOCTL_WRITE:

			if (pIOCTL->dioc_InBuf==NULL
				|| pIOCTL->dioc_cbInBuf<sizeof(VMHANDLE)+1) {
				DBTRACE(0,"!INVALID INBUF");
				return(SBBSEXEC_ERROR_INBUF);
			}

			if (pIOCTL->dioc_OutBuf==NULL
				|| pIOCTL->dioc_cbOutBuf!=sizeof(DWORD)) {
				DBTRACE(0,"!INVALID OUTBUF");
				return(SBBSEXEC_ERROR_OUTBUF);
			}

			vm = find_vm(*(VMHANDLE*)pIOCTL->dioc_InBuf);
			if(vm==NULL) {
				DBTRACE(0,"!NO VM LIST");
				return(SBBSEXEC_ERROR_INDATA);
			}

			wr = pIOCTL->dioc_cbInBuf-sizeof(VMHANDLE);

			avail = RingBufFree(&vm->in);

			if(wr>avail) {
				DBTRACEdd(0,"Reducing write size", wr, avail);
				wr=avail;
			}

			RingBufWrite(&vm->in, (BYTE*)pIOCTL->dioc_InBuf+sizeof(VMHANDLE), wr);

			*(DWORD *)pIOCTL->dioc_OutBuf = wr;

			if(pIOCTL->dioc_bytesret!=NULL)
				*pIOCTL->dioc_bytesret = sizeof(DWORD);

            if(vm->input_sem!=NULL) // Wake up int14 handler
            	Signal_Semaphore(vm->input_sem);

			// Wake up the VDM (improves keyboard response - dramatically!)
			Wake_Up_VM(vm->handle);
			break;

		case SBBSEXEC_IOCTL_DISCONNECT:
			DBTRACEd(0,"IOCTL: DISCONNECT",Get_System_Time());

			if (pIOCTL->dioc_InBuf==NULL
				|| pIOCTL->dioc_cbInBuf!=sizeof(VMHANDLE)) {
				DBTRACE(0,"!INVALID INBUF");
				return(SBBSEXEC_ERROR_INBUF);
			}

			vm = find_vm(*(VMHANDLE*)pIOCTL->dioc_InBuf);
			if(vm==NULL) {
				DBTRACE(0,"!NO VM LIST");
				return(SBBSEXEC_ERROR_INDATA);
			}

			vm->online=false;

            if(vm->input_sem!=NULL) // Wake up int14 handler
            	Signal_Semaphore(vm->input_sem);
            if(vm->output_sem!=NULL) // Wake up int14 handler
            	Signal_Semaphore(vm->output_sem);
			break;

		case SBBSEXEC_IOCTL_STOP:
			DBTRACEd(0,"IOCTL: STOP",Get_System_Time());

			if (pIOCTL->dioc_InBuf==NULL
				|| pIOCTL->dioc_cbInBuf!=sizeof(VMHANDLE)) {
				DBTRACE(0,"!INVALID INBUF");
				return(SBBSEXEC_ERROR_INBUF);
			}

			vm = find_vm(*(VMHANDLE*)pIOCTL->dioc_InBuf);
			if(vm==NULL) {
				DBTRACE(0,"!NO VM LIST");
				return(SBBSEXEC_ERROR_INDATA);
			}

			DBTRACEx(0,"CLOSING VM HANDLE", vm->handle);
			vm->handle=NULL;	// Mark as available
			RingBufDispose(&vm->in);
			RingBufDispose(&vm->out);
            if(vm->input_sem!=NULL) // Wake up int14 handler
            	Signal_Semaphore(vm->input_sem);
            if(vm->output_sem!=NULL) // Wake up int14 handler
            	Signal_Semaphore(vm->output_sem);

			vm->input_sem=NULL;
			vm->output_sem=NULL;

			break;

		default:
			DBTRACEdx(0,"!UNKNOWN IOCTL"
				,pIOCTL->dioc_IOCtlCode,pIOCTL->dioc_IOCtlCode);
			return(SBBSEXEC_ERROR_IOCTL);

	}
	return (0);	// DEVIOCTL_NOERROR);
}
示例#12
0
BOOL SBBSExecInt14::handler(VMHANDLE hVM, CLIENT_STRUCT* pRegs, DWORD intno)
{
	BYTE*	buffer;
	BYTE	ch;
	WORD	buflen;
    WORD	rd,wr;
    WORD	avail;
	vm_t*	vm = find_vm(hVM);

	if(vm==NULL || vm->mode!=SBBSEXEC_MODE_FOSSIL) {
		return(FALSE); // Tells VMM that interrupt was not handled
	}


	DBTRACEx(4,"Int14 func",_clientAH);

	switch(_clientAH) {
		case 0x00:	/* Initialize/Set baud rate */
        	DBTRACE(0,"Int14 init");
			_clientAX=PortStatus(vm);
			break;
		case 0x01: /* write char to com port */
        	if(RingBufFree(&vm->out)<2) {
            	DBTRACEx(1,"!OUTPUT BUFFER OVERFLOW, hVM", hVM);
            	vm->output_sem=Create_Semaphore(0);
                Wait_Semaphore(vm->output_sem,BLOCK_THREAD_IDLE);
                Destroy_Semaphore(vm->output_sem);
                vm->output_sem=NULL;
                if(!vm->online) {
                	DBTRACE(0,"!USER HUNG UP");
                	return(true);
                }
            }
			ch=_clientAL;
			RingBufWrite(&vm->out,&ch,1);
#if 0	/* Now done in SBBS.DLL/XTRN.CPP */
			if(ch==0xff) { /* escape TELNET IAC */
				RingBufWrite(&vm->out,&ch,1);
				DBTRACE(1,"Escaped IAC in output stream");
			}
#endif
			vm->overrun=false;
			_clientAX=PortStatus(vm);
			break;
		case 0x02: /* read char from com port */
			if(!RingBufFull(&vm->in)) {
            	DBTRACEx(0,"Waiting on input semaphore, hVM", hVM);
            	vm->input_sem=Create_Semaphore(0);
                Wait_Semaphore(vm->input_sem,BLOCK_THREAD_IDLE);
                Destroy_Semaphore(vm->input_sem);
                vm->input_sem=NULL;
#if 0
				_clientAH=0x80;	/* timed-out */
				return(TRUE);
#endif
			}
			RingBufRead(&vm->in,&ch,1);
			_clientAH=0;
			_clientAL=ch;
			break;
		case 0x03:	/* request status */
			_clientAX=PortStatus(vm);
			break;
		case 0x04:	/* initialize */
			DBTRACE(0,"Int14 func 4 init");
			_clientAX=0x1954;	/* magic number = success */
			_clientBH=5;		/* FOSSIL rev */
			_clientBL=0x1B;		/* maximum FOSSIL func supported */
			break;
        case 0x08:	// flush output buffer
            DBTRACE(0,"Int14 FLUSH OUTPUT BUFFER");
            vm->output_sem=Create_Semaphore(0);
            Wait_Semaphore(vm->output_sem,BLOCK_THREAD_IDLE);
            Destroy_Semaphore(vm->output_sem);
            vm->output_sem=NULL;
			break;
        case 0x09:	// purge output buffer
        	DBTRACE(0,"Int14 PURGE OUTPUT BUFFER");
        	RingBufReInit(&vm->out);
            break;
        case 0x0A:	// purge input buffer
        	DBTRACE(0,"Int14 PURGE INPUT BUFFER");
        	RingBufReInit(&vm->in);
            break;
		case 0x0B: /* write char to com port, no wait */
        	if(RingBufFree(&vm->out)<2) {
            	_clientAX=0; // char was not accepted
                break;
            }
			ch=_clientAL;
			RingBufWrite(&vm->out,&ch,1);
#if 0	/* Now done in SBBS.DLL/XTRN.CPP */
			if(ch==0xff) { /* escape TELNET IAC */
				RingBufWrite(&vm->out,&ch,1);
				DBTRACE(1,"Escaped IAC in output stream");
			}
#endif
			_clientAX=1; // char was accepted
			break;
        case 0x0C:	// non-destructive read-ahead
			if(!RingBufFull(&vm->in)) {
				_clientAX=0xffff;	// no char available
				break;
			}
			RingBufPeek(&vm->in,&ch,1);
			_clientAH=0;
			_clientAL=ch;
			break;
		case 0x13:	/* write to display */
			dprintf("%c",_clientAL);
			break;
        case 0x18:	/* read bock */
        	rd=_clientCX;
            avail=RingBufFull(&vm->in);
            if(rd>avail)
            	rd=avail;
            if(rd) {
	            buffer = (BYTE*)MAPFLAT(CRS.Client_ES, CWRS.Client_DI);
                rd = RingBufRead(&vm->in, buffer, rd);
            }
            _clientAX = rd;
            break;
        case 0x19:	/* write block */
			wr=_clientCX;
            avail=RingBufFree(&vm->out);
            if(wr>avail)
            	wr=avail;
            if(wr) {
	            buffer = (BYTE*)MAPFLAT(CRS.Client_ES, CWRS.Client_DI);
                wr = RingBufWrite(&vm->out, buffer, wr);
            }
            _clientAX = wr;
            break;
#if 1
        case 0x1B:	// driver info
        {
        	DBTRACE(1,"Int14 driver info");
            struct {
                WORD    info_size;
                BYTE	curr_fossil;
                BYTE	curr_rev;
                DWORD	id_string;
                WORD	inbuf_size;
                WORD	inbuf_free;
                WORD	outbuf_size;
                WORD	outbuf_free;
                BYTE	screen_width;
                BYTE	screen_height;
                BYTE	baud_rate;
            } info={ sizeof(info), 5, 1, 0
            		,RINGBUF_SIZE_IN-1, RingBufFree(&vm->in)
                    ,RINGBUF_SIZE_OUT-1, RingBufFree(&vm->out)
                    ,80,25
                    ,1 // 38400
                    };
//			Map_Lin_To_VM_Addr
			buffer = (BYTE*)MAPFLAT(CRS.Client_ES, CWRS.Client_DI);
            wr=sizeof(info);
            if(wr>_clientCX)
            	wr=_clientCX;
            memcpy(buffer, &info, wr);
        	_clientAX=wr;
            break;
		}
#endif
		default:
			DBTRACEx(0,"!UNHANDLED INTERRUPT 14h function",_clientAH);
			break;
	}
	return(TRUE);	// Tells VMM that interrupt was handled
}
示例#13
0
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
BOOL SBBSExecInt21::handler(VMHANDLE hVM, CLIENT_STRUCT* pRegs, DWORD intno)
{
	BYTE	ch;
	BYTE*	buffer;
	WORD	buflen;
	vm_t*	vm = find_vm(hVM);

	if(vm==NULL || !(vm->mode&SBBSEXEC_MODE_DOS_OUT)) {
#if 0
		if(vm && !(vm->mode&SBBSEXEC_MODE_DOS_OUT)) {
			DBTRACEx(0,"Int21 on unsupported VM", hVM);
		}
#endif
		return(FALSE); // Tells VMM that interrupt was not handled
	}
	DBTRACEx(1,"Int21 function", _clientAH);

	DWORD avail = RingBufFree(&vm->out);

    switch(_clientAH) {
    	case 0x01:
            DBTRACE(0,"!Int21 Char input WITH echo");
            break;
        case 0x06:	// Direct console I/O
			DBTRACEx(0,"DOS DIRECT CONSOLE IO, DL", _clientDL);
			if(_clientDL==0xff)  {
				avail=RingBufFull(&vm->in);
				if(avail) {
					DBTRACEd(0,"avail",avail);
		            RingBufRead(&vm->in, &ch, 1);
					_clientFlags&=~(1<<6);	// clear zero flag
					_clientAX=ch;
					return(TRUE);
				}
				break;
			}
			// fall-through
    	case 0x02:	// Character output
			DBTRACEx(1,"Int21 function", _clientAH);
            if(!avail) {
                DBTRACEx(0,"!OUTPUT BUFFER OVERFLOW, hVM", hVM);
                vm->overrun=true;
				break;
            }
            ch=_clientDL;
            RingBufWrite(&vm->out,&ch,1);
            vm->overrun=false;
			break;
		case 0x09:	// Display string
			DBTRACE(0,"!Int21 func 09 - DISPLAY STRING");
			break;
		case 0x0A:	// Buffered keyboard input
			DBTRACE(0,"Int21 Func 0A - Buffered Keyboard Input");
			/* Need to get a string from the user, echo, and copy to DS:DX */
			/* byte 0 = max length, byte 1 = actual read (minus CR) */
			break;
        case 0x40:	// Write file or device
			if(_clientBX!=1 && _clientBX!=2) {	// !stdout and !stderr
            	DBTRACEd(1,"!Int21 write to unsupported device", _clientBX);
				break;
            }
			DBTRACEdd(1,"Int21 write file", _clientBX, _clientCX);
            buffer = (BYTE*)MAPFLAT(CRS.Client_DS, CWRS.Client_DX);
            buflen = _clientCX;
            if(avail<buflen) {
                DBTRACEd(0,"!OUTPUT BUFFER OVERFLOW, avail", avail);
                vm->overrun=true;
                if(!avail)
					break;
                buflen=avail;
            }
            RingBufWrite(&vm->out,buffer,buflen);
            vm->overrun=false;
            break;
    }

	return(FALSE);	// Tells VMM that interrupt was not handled
}
示例#14
0
文件: sexyz.c 项目: ftnapps/pkg-sbbs
static void output_thread(void* arg)
{
	char		stats[128];
    BYTE		buf[MAX_OUTBUF_SIZE];
	int			i;
    ulong		avail;
	ulong		total_sent=0;
	ulong		total_pkts=0;
	ulong		short_sends=0;
    ulong		bufbot=0;
    ulong		buftop=0;
	fd_set		socket_set;
	struct timeval tv;

#if 0 /* def _DEBUG */
	fprintf(statfp,"output thread started\n");
#endif

	while(sock!=INVALID_SOCKET && !terminate) {

		if(bufbot==buftop)
	    	avail=RingBufFull(&outbuf);
		else
        	avail=buftop-bufbot;

		if(!avail) {
#if !defined(RINGBUF_EVENT)
			SetEvent(outbuf_empty);
#endif
			sem_wait(&outbuf.sem);
			if(outbuf.highwater_mark)
				sem_trywait_block(&outbuf.highwater_sem,outbuf_drain_timeout);
			continue; 
		}

		/* Check socket for writability (using select) */
		tv.tv_sec=0;
		tv.tv_usec=1000;

		FD_ZERO(&socket_set);
#ifdef __unix__
		if(stdio)
			FD_SET(STDOUT_FILENO,&socket_set);
		else
#endif
			FD_SET(sock,&socket_set);

		i=select(sock+1,NULL,&socket_set,NULL,&tv);
		if(i==SOCKET_ERROR) {
			lprintf(LOG_ERR,"ERROR %d selecting socket %u for send"
				,ERROR_VALUE,sock);
			break;
		}
		if(i<1) {
			select_errors++;
			continue;
		}

        if(bufbot==buftop) { /* linear buf empty, read from ring buf */
            if(avail>sizeof(buf)) {
                lprintf(LOG_ERR,"Insufficient linear output buffer (%lu > %lu)"
					,avail, sizeof(buf));
                avail=sizeof(buf);
            }
            buftop=RingBufRead(&outbuf, buf, avail);
            bufbot=0;
        }
#ifdef __unix__
		if(stdio)
			i=write(STDOUT_FILENO, (char*)buf+bufbot, buftop-bufbot);
		else
#endif
			i=sendsocket(sock, (char*)buf+bufbot, buftop-bufbot);
		if(i==SOCKET_ERROR) {
        	if(ERROR_VALUE == ENOTSOCK)
                lprintf(LOG_ERR,"client socket closed on send");
            else if(ERROR_VALUE==ECONNRESET) 
				lprintf(LOG_ERR,"connection reset by peer on send");
            else if(ERROR_VALUE==ECONNABORTED) 
				lprintf(LOG_ERR,"connection aborted by peer on send");
			else
				lprintf(LOG_ERR,"ERROR %d sending on socket %d"
                	,ERROR_VALUE, sock);
			break;
		}

		if(debug_tx)
			dump(buf+bufbot,i);

		if(i!=(int)(buftop-bufbot)) {
			lprintf(LOG_ERR,"Short socket send (%u instead of %u)"
				,i ,buftop-bufbot);
			short_sends++;
		}
		bufbot+=i;
		total_sent+=i;
		total_pkts++;
    }

	if(total_sent)
		sprintf(stats,"(sent %lu bytes in %lu blocks, %lu average, %lu short, %lu errors)"
			,total_sent, total_pkts, total_sent/total_pkts, short_sends, select_errors);
	else
		stats[0]=0;

	lprintf(LOG_DEBUG,"output thread terminated\n%s", stats);
}
示例#15
0
//*****************************************************************************
//
// Gets a message from the UART buffer.
//
// \param pui8Msg is a pointer to storage allocated by the caller where the
// message will be copied to.
//
// \param ui16Length is the length of the pui8Msg buffer.
//
// Copies a message from the UART buffer to the \e pui8Msg caller supplied
// storage.  If the caller supplied storage length is less than the next
// UART message length then the UART message is dumped and no data is returned.
// Therefore it is critical to make sure that caller supplies sufficient length
// for the longest anticipated message from the RNP.  256 bytes is recommended.
//
// \return None.
//
//*****************************************************************************
void
RemoTIUARTGetMsg(uint8_t* pui8Msg, uint_fast16_t ui16Length)
{
    bool bIntState;
    uint8_t ui8MsgLength;
    uint8_t ui8SOF;

    //
    // State previous state of master interrupt enable then disable all
    // interrupts.
    //
    bIntState = IntMasterDisable();

    //
    // Determine if a message is in the buffer available for the caller.
    //
    if(g_ui16RxMsgCount != 0)
    {
       //
       // Read out the SOF and Msg Length characters.
       //
       ui8SOF = RingBufReadOne(&g_rbRemoTIRxRingBuf);
       ui8MsgLength = RingBufReadOne(&g_rbRemoTIRxRingBuf);

       //
       // Make sure that the user buffer has room for the message and the
       // packet overhead bytes.
       //
       if((ui8MsgLength + 5) <= ui16Length)
       {
           //
           // We have enough room, so store the two already bytes in the user
           // buffer.
           //
           pui8Msg[0] = ui8SOF;
           pui8Msg[1] = ui8MsgLength;

           //
           // Read the remaining bytes to the user buffer.
           //
           RingBufRead(&g_rbRemoTIRxRingBuf, pui8Msg + 2, ui8MsgLength + 3);

       }
       else
       {
           //
           // The user did not provide enough room and we cannot easily put
           // the first couple of bytes back into the buffer.  Therefore,
           // we dump the remainder of the message.
           //
           RingBufAdvanceRead(&g_rbRemoTIRxRingBuf, ui8MsgLength + 3);
       }

       //
       // Decrement the msg counter. Now one less message in the UART buffer.
       //
       g_ui16RxMsgCount -= 1;
    }

    //
    // Restore the master interrupt enable state.
    //
    if(!bIntState)
    {
        IntMasterEnable();
    }

    //
    // Finished.
    //
}
示例#16
0
void sbbs_t::telnet_gate(char* destaddr, ulong mode, char* client_user_name, char* server_user_name, char* term_type)
{
	char*	p;
	uchar	buf[512];
	int		i;
	int		rd;
	uint	attempts;
	ulong	l;
	bool	gotline;
	ushort	port;
	ulong	ip_addr;
	ulong	save_console;
	SOCKET	remote_socket;
	SOCKADDR_IN	addr;

	if(mode&TG_RLOGIN)
		port=513;
	else
		port=IPPORT_TELNET;

	p=strchr(destaddr,':');
	if(p!=NULL) {
		*p=0;
		port=atoi(p+1);
	}

	ip_addr=resolve_ip(destaddr);
	if(ip_addr==INADDR_NONE) {
		lprintf(LOG_NOTICE,"!TELGATE Failed to resolve address: %s",destaddr);
		bprintf("!Failed to resolve address: %s\r\n",destaddr);
		return;
	}

    if((remote_socket = open_socket(SOCK_STREAM, client.protocol)) == INVALID_SOCKET) {
		errormsg(WHERE,ERR_OPEN,"socket",0);
		return;
	}

	memset(&addr,0,sizeof(addr));
	addr.sin_addr.s_addr = htonl(startup->telnet_interface);
	addr.sin_family = AF_INET;

	if((i=bind(remote_socket, (struct sockaddr *) &addr, sizeof (addr)))!=0) {
		lprintf(LOG_NOTICE,"!TELGATE ERROR %d (%d) binding to socket %d",i, ERROR_VALUE, remote_socket);
		bprintf("!ERROR %d (%d) binding to socket\r\n",i, ERROR_VALUE);
		close_socket(remote_socket);
		return;
	}

	memset(&addr,0,sizeof(addr));
	addr.sin_addr.s_addr = ip_addr;
	addr.sin_family = AF_INET;
	addr.sin_port   = htons(port);

	if((i=connect(remote_socket, (struct sockaddr *)&addr, sizeof(addr)))!=0) {
		lprintf(LOG_NOTICE,"!TELGATE ERROR %d (%d) connecting to server: %s"
			,i,ERROR_VALUE, destaddr);
		bprintf("!ERROR %d (%d) connecting to server: %s\r\n"
			,i,ERROR_VALUE, destaddr);
		close_socket(remote_socket);
		return;
	}

	l=1;

	if((i = ioctlsocket(remote_socket, FIONBIO, &l))!=0) {
		lprintf(LOG_NOTICE,"!TELGATE ERROR %d (%d) disabling socket blocking"
			,i, ERROR_VALUE);
		close_socket(remote_socket);
		return;
	}

	lprintf(LOG_INFO,"Node %d %s gate to %s port %u on socket %d"
		,cfg.node_num
		,mode&TG_RLOGIN ? "RLogin" : "Telnet"
		,destaddr,port,remote_socket);

	if(!(mode&TG_CTRLKEYS))
		console|=CON_RAW_IN;

	if(mode&TG_RLOGIN) {
		p=(char*)buf;
		*(p++)=0;
		p+=sprintf(p,"%s",client_user_name==NULL ? useron.alias : client_user_name);
		p++;	// Add NULL
		p+=sprintf(p,"%s",server_user_name==NULL ? useron.name : server_user_name);
		p++;	// Add NULL
		if(term_type!=NULL)
			p+=sprintf(p,"%s",term_type);
		else
			p+=sprintf(p,"%s/%u",terminal, cur_rate);
		p++;	// Add NULL
		l=p-(char*)buf;
		sendsocket(remote_socket,(char*)buf,l);
		mode|=TG_NOLF;	/* Send LF (to remote host) when Telnet client sends CRLF (when not in binary mode) */
	}

	/* This is required for gating to Unix telnetd */
	if(mode&TG_NOTERMTYPE)
		request_telnet_opt(TELNET_DONT,TELNET_TERM_TYPE, 3000);	// Re-negotiation of terminal type

	/* Text/NVT mode by default */
	request_telnet_opt(TELNET_DONT,TELNET_BINARY_TX, 3000);

	if(!(telnet_mode&TELNET_MODE_OFF) && (mode&TG_PASSTHRU))
		telnet_mode|=TELNET_MODE_GATE;	// Pass-through telnet commands

	while(online) {
		if(!(mode&TG_NOCHKTIME))
			gettimeleft();
		rd=RingBufRead(&inbuf,buf,sizeof(buf));
		if(rd) {
#if 0
			if(memchr(buf,TELNET_IAC,rd)) {
				char dump[2048];
				dump[0];
				p=dump;
				for(int i=0;i<rd;i++)
					p+=sprintf(p,"%u ",buf[i]);
				lprintf(LOG_DEBUG,"Node %d Telnet cmd from client: %s", cfg.node_num, dump);
			}
#endif
			if(telnet_remote_option[TELNET_BINARY_TX]!=TELNET_WILL) {
				if(*buf==0x1d) { // ^]
					save_console=console;
					console&=~CON_RAW_IN;	// Allow Ctrl-U/Ctrl-P
					CRLF;
					while(online) {
						SYNC;
						mnemonics("\1n\r\n\1h\1bTelnet Gate: \1y~D\1wisconnect, "
							"\1y~E\1wcho toggle, \1y~L\1wist Users, \1y~P\1wrivate message, "
							"\1y~Q\1wuit: ");
						switch(getkeys("DELPQ",0)) {
							case 'D':
								closesocket(remote_socket);
								break;
							case 'E':
								mode^=TG_ECHO;
								bprintf(text[EchoIsNow]
									,mode&TG_ECHO
									? text[ON]:text[OFF]);
								continue;
							case 'L':
								whos_online(true);
								continue;
							case 'P':
								nodemsg();
								continue;
						}
						break;
					}
					attr(LIGHTGRAY);
					console=save_console;
				}
				else if(*buf<' ' && (mode&TG_CTRLKEYS))
					handle_ctrlkey(*buf, K_NONE);
				gotline=false;
				if((mode&TG_LINEMODE) && buf[0]!='\r') {
					ungetkey(buf[0]);
					l=K_CHAT;
					if(!(mode&TG_ECHO))
						l|=K_NOECHO;
					rd=getstr((char*)buf,sizeof(buf)-1,l);
					if(!rd)
						continue;
					strcat((char*)buf,crlf);
					rd+=2;
					gotline=true;
				}
				if((mode&TG_CRLF) && buf[rd-1]=='\r')
					buf[rd++]='\n';
				else if((mode&TG_NOLF) && buf[rd-1]=='\n')
					rd--;
				if(!gotline && (mode&TG_ECHO) && rd) {
					RingBufWrite(&outbuf,buf,rd);
				}
			} /* Not Telnet Binary mode */
			if(rd > 0) {
				for(attempts=0;attempts<60 && online; attempts++) /* added retry loop here, Jan-20-2003 */
				{
					if((i=sendsocket(remote_socket,(char*)buf,rd))>=0)
						break;
					if(ERROR_VALUE!=EWOULDBLOCK)
						break;
					mswait(500);
				} 
				if(i<0) {
					lprintf(LOG_NOTICE,"!TELGATE ERROR %d sending on socket %d",ERROR_VALUE,remote_socket);
					break;
				}
			}
		}
		rd=recv(remote_socket,(char*)buf,sizeof(buf),0);
		if(rd<0) {
			if(ERROR_VALUE==EWOULDBLOCK) {
				if(mode&TG_NODESYNC) {
					SYNC;
				} else {
					// Check if the node has been interrupted
					getnodedat(cfg.node_num,&thisnode,0);
					if(thisnode.misc&NODE_INTR)
						break;
				}
				YIELD();
				continue;
			}
			lprintf(LOG_NOTICE,"!TELGATE ERROR %d receiving on socket %d",ERROR_VALUE,remote_socket);
			break;
		}
		if(!rd) {
			lprintf(LOG_INFO,"Node %d Telnet gate disconnected",cfg.node_num);
			break;
		}
#if 0
		if(memchr(buf,TELNET_IAC,rd)) {
			char dump[2048];
			dump[0];
			p=dump;
			for(int i=0;i<rd;i++)
				p+=sprintf(p,"%u ",buf[i]);
			lprintf(LOG_DEBUG,"Node %d Telnet cmd from server: %s", cfg.node_num, dump);
		}
#endif
		RingBufWrite(&outbuf,buf,rd);
	}
	console&=~CON_RAW_IN;
	telnet_mode&=~TELNET_MODE_GATE;

	/* Disable Telnet Terminal Echo */
	request_telnet_opt(TELNET_WILL,TELNET_ECHO);

	close_socket(remote_socket);

	lprintf(LOG_INFO,"Node %d Telnet gate to %s finished",cfg.node_num,destaddr);
}