Need separate output buffers for each thread
git-svn-id: svn://svn.code.sf.net/p/nuttx/code/trunk@860 42af7a65-404d-4744-a932-0658087f49c3
This commit is contained in:
parent
6dad5e248b
commit
029d82031f
@ -91,13 +91,10 @@
|
|||||||
struct telnetio_s
|
struct telnetio_s
|
||||||
{
|
{
|
||||||
sem_t tio_sem;
|
sem_t tio_sem;
|
||||||
pid_t tio_holder;
|
|
||||||
int tio_sockfd;
|
int tio_sockfd;
|
||||||
uint16 tio_sndlen;
|
|
||||||
uint8 tio_bufndx;
|
uint8 tio_bufndx;
|
||||||
uint8 tio_state;
|
uint8 tio_state;
|
||||||
uint8 tio_semnest;
|
char tio_inbuffer[CONFIG_EXAMPLES_NSH_IOBUFFER_SIZE];
|
||||||
char tio_buffer[CONFIG_EXAMPLES_NSH_IOBUFFER_SIZE];
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct redirect_s
|
struct redirect_s
|
||||||
@ -119,12 +116,14 @@ struct telnetsave_s
|
|||||||
struct telnetd_s
|
struct telnetd_s
|
||||||
{
|
{
|
||||||
struct nsh_vtbl_s tn_vtbl;
|
struct nsh_vtbl_s tn_vtbl;
|
||||||
|
uint16 tn_sndlen;
|
||||||
boolean tn_redirected;
|
boolean tn_redirected;
|
||||||
union
|
union
|
||||||
{
|
{
|
||||||
struct telnetio_s *tn;
|
struct telnetio_s *tn;
|
||||||
struct redirect_s rd;
|
struct redirect_s rd;
|
||||||
} u;
|
} u;
|
||||||
|
char tn_outbuffer[CONFIG_EXAMPLES_NSH_IOBUFFER_SIZE];
|
||||||
char tn_cmd[CONFIG_EXAMPLES_NSH_LINELEN];
|
char tn_cmd[CONFIG_EXAMPLES_NSH_LINELEN];
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -132,6 +131,7 @@ struct telnetd_s
|
|||||||
* Private Function Prototypes
|
* Private Function Prototypes
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
|
static void tio_semtake(struct telnetio_s *tio);
|
||||||
static FAR struct nsh_vtbl_s *nsh_telnetclone(FAR struct nsh_vtbl_s *vtbl);
|
static FAR struct nsh_vtbl_s *nsh_telnetclone(FAR struct nsh_vtbl_s *vtbl);
|
||||||
static void nsh_telnetrelease(FAR struct nsh_vtbl_s *vtbl);
|
static void nsh_telnetrelease(FAR struct nsh_vtbl_s *vtbl);
|
||||||
static int nsh_telnetoutput(FAR struct nsh_vtbl_s *vtbl, const char *fmt, ...);
|
static int nsh_telnetoutput(FAR struct nsh_vtbl_s *vtbl, const char *fmt, ...);
|
||||||
@ -151,33 +151,15 @@ static void nsh_telnetexit(FAR struct nsh_vtbl_s *vtbl);
|
|||||||
|
|
||||||
static void tio_semtake(struct telnetio_s *tio)
|
static void tio_semtake(struct telnetio_s *tio)
|
||||||
{
|
{
|
||||||
pid_t my_pid = getpid();
|
/* Take the semaphore (perhaps waiting) */
|
||||||
|
|
||||||
/* Does this task already have the semaphore? */
|
while (sem_wait(&tio->tio_sem) != 0)
|
||||||
|
|
||||||
if (tio->tio_holder == my_pid)
|
|
||||||
{
|
{
|
||||||
/* Yes, just increment the number of references that the task holds */
|
/* The only case that an error should occur here is if the wait was
|
||||||
|
* awakened by a signal.
|
||||||
|
*/
|
||||||
|
|
||||||
tio->tio_semnest++;
|
ASSERT(errno == EINTR);
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
/* No, Take the semaphore (perhaps waiting) */
|
|
||||||
|
|
||||||
while (sem_wait(&tio->tio_sem) != 0)
|
|
||||||
{
|
|
||||||
/* The only case that an error should occur here is if the wait was
|
|
||||||
* awakened by a signal.
|
|
||||||
*/
|
|
||||||
|
|
||||||
ASSERT(errno == EINTR);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Stake the claim and return */
|
|
||||||
|
|
||||||
tio->tio_holder = my_pid;
|
|
||||||
tio->tio_semnest = 1;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -185,31 +167,7 @@ static void tio_semtake(struct telnetio_s *tio)
|
|||||||
* Name: tio_semgive
|
* Name: tio_semgive
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
static void tio_semgive(struct telnetio_s *tio)
|
#define tio_semgive(tio) ASSERT(sem_post(&tio->tio_sem) == 0)
|
||||||
{
|
|
||||||
pid_t my_pid = getpid();
|
|
||||||
|
|
||||||
/* I better be holding at least one count on the semaphore */
|
|
||||||
|
|
||||||
ASSERT(tio->tio_holder == my_pid);
|
|
||||||
|
|
||||||
/* Do I hold multiple references to the semphore */
|
|
||||||
|
|
||||||
if (tio->tio_semnest > 1)
|
|
||||||
{
|
|
||||||
/* Yes, just release one count and return */
|
|
||||||
|
|
||||||
tio->tio_semnest--;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
/* Nope, this is the last reference I have */
|
|
||||||
|
|
||||||
tio->tio_holder = -1;
|
|
||||||
tio->tio_semnest = 0;
|
|
||||||
ASSERT(sem_post(&tio->tio_sem) == 0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* Name: nsh_dumpbuffer
|
* Name: nsh_dumpbuffer
|
||||||
@ -393,10 +351,12 @@ static void nsh_sendopt(struct telnetd_s *pstate, uint8 option, uint8 value)
|
|||||||
optbuf[3] = 0;
|
optbuf[3] = 0;
|
||||||
|
|
||||||
nsh_dumpbuffer("Send optbuf", optbuf, 4);
|
nsh_dumpbuffer("Send optbuf", optbuf, 4);
|
||||||
|
tio_semtake(tio); /* Only one call to send at a time */
|
||||||
if (send(tio->tio_sockfd, optbuf, 4, 0) < 0)
|
if (send(tio->tio_sockfd, optbuf, 4, 0) < 0)
|
||||||
{
|
{
|
||||||
dbg("[%d] Failed to send TELNET_IAC: %d\n", tio->tio_sockfd, errno);
|
dbg("[%d] Failed to send TELNET_IAC: %d\n", tio->tio_sockfd, errno);
|
||||||
}
|
}
|
||||||
|
tio_semgive(tio);
|
||||||
}
|
}
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
@ -411,17 +371,17 @@ static void nsh_flush(FAR struct telnetd_s *pstate)
|
|||||||
{
|
{
|
||||||
struct telnetio_s *tio = pstate->u.tn;
|
struct telnetio_s *tio = pstate->u.tn;
|
||||||
|
|
||||||
tio_semtake(tio);
|
if (pstate->tn_sndlen > 0)
|
||||||
if (tio->tio_sndlen > 0)
|
|
||||||
{
|
{
|
||||||
nsh_dumpbuffer("Shell output", tio->tio_buffer, tio->tio_sndlen);
|
nsh_dumpbuffer("Shell output", pstate->tn_outbuffer, pstate->tn_sndlen);
|
||||||
if (send(tio->tio_sockfd, tio->tio_buffer, tio->tio_sndlen, 0) < 0)
|
tio_semtake(tio); /* Only one call to send at a time */
|
||||||
|
if (send(tio->tio_sockfd, pstate->tn_outbuffer, pstate->tn_sndlen, 0) < 0)
|
||||||
{
|
{
|
||||||
dbg("[%d] Failed to send response: %d\n", tio->tio_sockfd, errno);
|
dbg("[%d] Failed to send response: %d\n", tio->tio_sockfd, errno);
|
||||||
}
|
}
|
||||||
|
tio_semgive(tio);
|
||||||
}
|
}
|
||||||
tio->tio_sndlen = 0;
|
pstate->tn_sndlen = 0;
|
||||||
tio_semgive(tio);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
@ -435,10 +395,9 @@ static void nsh_flush(FAR struct telnetd_s *pstate)
|
|||||||
static int nsh_receive(struct telnetd_s *pstate, size_t len)
|
static int nsh_receive(struct telnetd_s *pstate, size_t len)
|
||||||
{
|
{
|
||||||
struct telnetio_s *tio = pstate->u.tn;
|
struct telnetio_s *tio = pstate->u.tn;
|
||||||
char *ptr = tio->tio_buffer;
|
char *ptr = tio->tio_inbuffer;
|
||||||
uint8 ch;
|
uint8 ch;
|
||||||
|
|
||||||
tio_semtake(tio);
|
|
||||||
while (len > 0)
|
while (len > 0)
|
||||||
{
|
{
|
||||||
ch = *ptr++;
|
ch = *ptr++;
|
||||||
@ -520,7 +479,6 @@ static int nsh_receive(struct telnetd_s *pstate, size_t len)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
tio_semgive(tio);
|
|
||||||
return OK;
|
return OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -569,13 +527,13 @@ static void *nsh_connection(void *arg)
|
|||||||
|
|
||||||
/* Read a buffer of data from the TELNET client */
|
/* Read a buffer of data from the TELNET client */
|
||||||
|
|
||||||
ret = recv(tio->tio_sockfd, tio->tio_buffer, CONFIG_EXAMPLES_NSH_IOBUFFER_SIZE, 0);
|
ret = recv(tio->tio_sockfd, tio->tio_inbuffer, CONFIG_EXAMPLES_NSH_IOBUFFER_SIZE, 0);
|
||||||
if (ret > 0)
|
if (ret > 0)
|
||||||
{
|
{
|
||||||
|
|
||||||
/* Process the received TELNET data */
|
/* Process the received TELNET data */
|
||||||
|
|
||||||
nsh_dumpbuffer("Received buffer", tio->tio_buffer, ret);
|
nsh_dumpbuffer("Received buffer", tio->tio_inbuffer, ret);
|
||||||
ret = nsh_receive(pstate, ret);
|
ret = nsh_receive(pstate, ret);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -618,19 +576,16 @@ static void *nsh_connection(void *arg)
|
|||||||
static int nsh_telnetoutput(FAR struct nsh_vtbl_s *vtbl, const char *fmt, ...)
|
static int nsh_telnetoutput(FAR struct nsh_vtbl_s *vtbl, const char *fmt, ...)
|
||||||
{
|
{
|
||||||
struct telnetd_s *pstate = (struct telnetd_s *)vtbl;
|
struct telnetd_s *pstate = (struct telnetd_s *)vtbl;
|
||||||
struct telnetio_s *tio = pstate->u.tn;
|
int nbytes = pstate->tn_sndlen;
|
||||||
int nbytes = tio->tio_sndlen;
|
|
||||||
int len;
|
int len;
|
||||||
va_list ap;
|
va_list ap;
|
||||||
|
|
||||||
tio_semtake(tio);
|
|
||||||
|
|
||||||
/* Put the new info into the buffer. Here we are counting on the fact that
|
/* Put the new info into the buffer. Here we are counting on the fact that
|
||||||
* no output strings will exceed CONFIG_EXAMPLES_NSH_LINELEN!
|
* no output strings will exceed CONFIG_EXAMPLES_NSH_LINELEN!
|
||||||
*/
|
*/
|
||||||
|
|
||||||
va_start(ap, fmt);
|
va_start(ap, fmt);
|
||||||
vsnprintf(&tio->tio_buffer[nbytes],
|
vsnprintf(&pstate->tn_outbuffer[nbytes],
|
||||||
(CONFIG_EXAMPLES_NSH_IOBUFFER_SIZE - 1) - nbytes, fmt, ap);
|
(CONFIG_EXAMPLES_NSH_IOBUFFER_SIZE - 1) - nbytes, fmt, ap);
|
||||||
va_end(ap);
|
va_end(ap);
|
||||||
|
|
||||||
@ -638,26 +593,25 @@ static int nsh_telnetoutput(FAR struct nsh_vtbl_s *vtbl, const char *fmt, ...)
|
|||||||
* buffered data
|
* buffered data
|
||||||
*/
|
*/
|
||||||
|
|
||||||
len = strlen(&tio->tio_buffer[nbytes]);
|
len = strlen(&pstate->tn_outbuffer[nbytes]);
|
||||||
nbytes += len;
|
nbytes += len;
|
||||||
|
|
||||||
/* Expand any terminating \n to \r\n */
|
/* Expand any terminating \n to \r\n */
|
||||||
|
|
||||||
if (nbytes < (CONFIG_EXAMPLES_NSH_IOBUFFER_SIZE - 2) &&
|
if (nbytes < (CONFIG_EXAMPLES_NSH_IOBUFFER_SIZE - 2) &&
|
||||||
tio->tio_buffer[nbytes-1] == '\n')
|
pstate->tn_outbuffer[nbytes-1] == '\n')
|
||||||
{
|
{
|
||||||
tio->tio_buffer[nbytes-1] = ISO_cr;
|
pstate->tn_outbuffer[nbytes-1] = ISO_cr;
|
||||||
tio->tio_buffer[nbytes] = ISO_nl;
|
pstate->tn_outbuffer[nbytes] = ISO_nl;
|
||||||
tio->tio_buffer[nbytes+1] = '\0';
|
pstate->tn_outbuffer[nbytes+1] = '\0';
|
||||||
nbytes++;
|
nbytes++;
|
||||||
}
|
}
|
||||||
tio->tio_sndlen = nbytes;
|
pstate->tn_sndlen = nbytes;
|
||||||
|
|
||||||
/* Flush to the network if the buffer does not have room for one more
|
/* Flush to the network if the buffer does not have room for one more
|
||||||
* maximum length string.
|
* maximum length string.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
tio_semgive(tio);
|
|
||||||
if (nbytes > CONFIG_EXAMPLES_NSH_IOBUFFER_SIZE - CONFIG_EXAMPLES_NSH_LINELEN)
|
if (nbytes > CONFIG_EXAMPLES_NSH_IOBUFFER_SIZE - CONFIG_EXAMPLES_NSH_LINELEN)
|
||||||
{
|
{
|
||||||
nsh_flush(pstate);
|
nsh_flush(pstate);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user