/[lwip]/lwip/src/api/api_lib.c
ViewVC logotype

Diff of /lwip/src/api/api_lib.c

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 1.11.2.1 by likewise, Thu Apr 17 10:00:37 2003 UTC revision 1.11.2.2 by likewise, Wed May 14 14:38:27 2003 UTC
# Line 45  netbuf *netbuf_new(void) Line 45  netbuf *netbuf_new(void)
45    struct netbuf *buf;    struct netbuf *buf;
46    
47    buf = memp_mallocp(MEMP_NETBUF);    buf = memp_mallocp(MEMP_NETBUF);
48    if(buf != NULL) {    if (buf != NULL) {
49      buf->p = NULL;      buf->p = NULL;
50      buf->ptr = NULL;      buf->ptr = NULL;
51      return buf;      return buf;
# Line 57  netbuf *netbuf_new(void) Line 57  netbuf *netbuf_new(void)
57  void  void
58  netbuf_delete(struct netbuf *buf)  netbuf_delete(struct netbuf *buf)
59  {  {
60    if(buf != NULL) {    if (buf != NULL) {
61      if(buf->p != NULL) {      if (buf->p != NULL) {
62        pbuf_free(buf->p);        pbuf_free(buf->p);
63        buf->p = buf->ptr = NULL;        buf->p = buf->ptr = NULL;
64      }      }
# Line 70  void * Line 70  void *
70  netbuf_alloc(struct netbuf *buf, u16_t size)  netbuf_alloc(struct netbuf *buf, u16_t size)
71  {  {
72    /* Deallocate any previously allocated memory. */    /* Deallocate any previously allocated memory. */
73    if(buf->p != NULL) {    if (buf->p != NULL) {
74      pbuf_free(buf->p);      pbuf_free(buf->p);
75    }    }
76    buf->p = pbuf_alloc(PBUF_TRANSPORT, size, PBUF_RAM);    buf->p = pbuf_alloc(PBUF_TRANSPORT, size, PBUF_RAM);
77    if(buf->p == NULL) {    if (buf->p == NULL) {
78       return NULL;       return NULL;
79    }    }
80    buf->ptr = buf->p;    buf->ptr = buf->p;
# Line 84  netbuf_alloc(struct netbuf *buf, u16_t s Line 84  netbuf_alloc(struct netbuf *buf, u16_t s
84  void  void
85  netbuf_free(struct netbuf *buf)  netbuf_free(struct netbuf *buf)
86  {  {
87    if(buf->p != NULL) {    if (buf->p != NULL) {
88      pbuf_free(buf->p);      pbuf_free(buf->p);
89    }    }
90    buf->p = buf->ptr = NULL;    buf->p = buf->ptr = NULL;
# Line 93  netbuf_free(struct netbuf *buf) Line 93  netbuf_free(struct netbuf *buf)
93  void  void
94  netbuf_ref(struct netbuf *buf, void *dataptr, u16_t size)  netbuf_ref(struct netbuf *buf, void *dataptr, u16_t size)
95  {  {
96    if(buf->p != NULL) {    if (buf->p != NULL) {
97      pbuf_free(buf->p);      pbuf_free(buf->p);
98    }    }
99    buf->p = pbuf_alloc(PBUF_TRANSPORT, 0, PBUF_REF);    buf->p = pbuf_alloc(PBUF_TRANSPORT, 0, PBUF_REF);
# Line 119  netbuf_len(struct netbuf *buf) Line 119  netbuf_len(struct netbuf *buf)
119  err_t  err_t
120  netbuf_data(struct netbuf *buf, void **dataptr, u16_t *len)  netbuf_data(struct netbuf *buf, void **dataptr, u16_t *len)
121  {  {
122    if(buf->ptr == NULL) {    if (buf->ptr == NULL) {
123      return ERR_BUF;      return ERR_BUF;
124    }    }
125    *dataptr = buf->ptr->payload;    *dataptr = buf->ptr->payload;
# Line 130  netbuf_data(struct netbuf *buf, void **d Line 130  netbuf_data(struct netbuf *buf, void **d
130  s8_t  s8_t
131  netbuf_next(struct netbuf *buf)  netbuf_next(struct netbuf *buf)
132  {  {
133    if(buf->ptr->next == NULL) {    if (buf->ptr->next == NULL) {
134      return -1;      return -1;
135    }    }
136    buf->ptr = buf->ptr->next;    buf->ptr = buf->ptr->next;
137    if(buf->ptr->next == NULL) {    if (buf->ptr->next == NULL) {
138      return 1;      return 1;
139    }    }
140    return 0;    return 0;
# Line 154  netbuf_copy_partial(struct netbuf *buf, Line 154  netbuf_copy_partial(struct netbuf *buf,
154    
155    left = 0;    left = 0;
156    
157    if(buf == NULL) {    if (buf == NULL) {
158      return;      return;
159    }    }
160        
161    /* This implementation is bad. It should use bcopy    /* This implementation is bad. It should use bcopy
162       instead. */       instead. */
163    for(p = buf->p; left < len && p != NULL; p = p->next) {    for(p = buf->p; left < len && p != NULL; p = p->next) {
164      if(offset != 0 && offset >= p->len) {      if (offset != 0 && offset >= p->len) {
165        offset -= p->len;        offset -= p->len;
166      } else {          } else {    
167        for(i = offset; i < p->len; ++i) {        for(i = offset; i < p->len; ++i) {
168          ((char *)dataptr)[left] = ((char *)p->payload)[i];          ((char *)dataptr)[left] = ((char *)p->payload)[i];
169          if(++left >= len) {          if (++left >= len) {
170            return;            return;
171          }          }
172        }        }
# Line 199  netconn *netconn_new(enum netconn_type t Line 199  netconn *netconn_new(enum netconn_type t
199    struct netconn *conn;    struct netconn *conn;
200    
201    conn = memp_mallocp(MEMP_NETCONN);    conn = memp_mallocp(MEMP_NETCONN);
202    if(conn == NULL) {    if (conn == NULL) {
203      return NULL;      return NULL;
204    }    }
205    conn->type = t;    conn->type = t;
206    conn->pcb.tcp = NULL;    conn->pcb.tcp = NULL;
207    
208    if((conn->mbox = sys_mbox_new()) == SYS_MBOX_NULL) {    if ((conn->mbox = sys_mbox_new()) == SYS_MBOX_NULL) {
209      memp_freep(MEMP_NETCONN, conn);      memp_freep(MEMP_NETCONN, conn);
210      return NULL;      return NULL;
211    }    }
# Line 239  netconn_delete(struct netconn *conn) Line 239  netconn_delete(struct netconn *conn)
239    struct api_msg *msg;    struct api_msg *msg;
240    void *mem;    void *mem;
241        
242    if(conn == NULL) {    if (conn == NULL) {
243      return ERR_OK;      return ERR_OK;
244    }    }
245        
246    if((msg = memp_mallocp(MEMP_API_MSG)) == NULL) {    if ((msg = memp_mallocp(MEMP_API_MSG)) == NULL) {
247      return ERR_MEM;      return ERR_MEM;
248    }    }
249        
# Line 254  netconn_delete(struct netconn *conn) Line 254  netconn_delete(struct netconn *conn)
254    memp_freep(MEMP_API_MSG, msg);    memp_freep(MEMP_API_MSG, msg);
255    
256    /* Drain the recvmbox. */    /* Drain the recvmbox. */
257    if(conn->recvmbox != SYS_MBOX_NULL) {    if (conn->recvmbox != SYS_MBOX_NULL) {
258      while(sys_arch_mbox_fetch(conn->recvmbox, &mem, 1) != SYS_ARCH_TIMEOUT) {      while (sys_arch_mbox_fetch(conn->recvmbox, &mem, 1) != SYS_ARCH_TIMEOUT) {
259        if(conn->type == NETCONN_TCP) {        if (conn->type == NETCONN_TCP) {
260          pbuf_free((struct pbuf *)mem);          pbuf_free((struct pbuf *)mem);
261        } else {        } else {
262          netbuf_delete((struct netbuf *)mem);          netbuf_delete((struct netbuf *)mem);
# Line 268  netconn_delete(struct netconn *conn) Line 268  netconn_delete(struct netconn *conn)
268    
269    
270    /* Drain the acceptmbox. */    /* Drain the acceptmbox. */
271    if(conn->acceptmbox != SYS_MBOX_NULL) {    if (conn->acceptmbox != SYS_MBOX_NULL) {
272      while(sys_arch_mbox_fetch(conn->acceptmbox, &mem, 1) != SYS_ARCH_TIMEOUT) {      while (sys_arch_mbox_fetch(conn->acceptmbox, &mem, 1) != SYS_ARCH_TIMEOUT) {
273        netconn_delete((struct netconn *)mem);        netconn_delete((struct netconn *)mem);
274      }      }
275            
# Line 279  netconn_delete(struct netconn *conn) Line 279  netconn_delete(struct netconn *conn)
279    
280    sys_mbox_free(conn->mbox);    sys_mbox_free(conn->mbox);
281    conn->mbox = SYS_MBOX_NULL;    conn->mbox = SYS_MBOX_NULL;
282    if(conn->sem != SYS_SEM_NULL) {    if (conn->sem != SYS_SEM_NULL) {
283      sys_sem_free(conn->sem);      sys_sem_free(conn->sem);
284    }    }
285    /*  conn->sem = SYS_SEM_NULL;*/    /*  conn->sem = SYS_SEM_NULL;*/
# Line 297  err_t Line 297  err_t
297  netconn_peer(struct netconn *conn, struct ip_addr *addr,  netconn_peer(struct netconn *conn, struct ip_addr *addr,
298               u16_t *port)               u16_t *port)
299  {  {
300    switch(conn->type) {    switch (conn->type) {
301    case NETCONN_UDPLITE:    case NETCONN_UDPLITE:
302    case NETCONN_UDPNOCHKSUM:    case NETCONN_UDPNOCHKSUM:
303    case NETCONN_UDP:    case NETCONN_UDP:
# Line 308  netconn_peer(struct netconn *conn, struc Line 308  netconn_peer(struct netconn *conn, struc
308      *port = conn->pcb.udp->remote_port;      *port = conn->pcb.udp->remote_port;
309      break;      break;
310    case NETCONN_TCP:    case NETCONN_TCP:
311      if(conn->pcb.tcp == NULL)      if (conn->pcb.tcp == NULL)
312        return ERR_CONN;        return ERR_CONN;
313      *addr = (conn->pcb.tcp->remote_ip);      *addr = (conn->pcb.tcp->remote_ip);
314      *port = conn->pcb.tcp->remote_port;      *port = conn->pcb.tcp->remote_port;
# Line 321  err_t Line 321  err_t
321  netconn_addr(struct netconn *conn, struct ip_addr **addr,  netconn_addr(struct netconn *conn, struct ip_addr **addr,
322               u16_t *port)               u16_t *port)
323  {  {
324    switch(conn->type) {    switch (conn->type) {
325    case NETCONN_UDPLITE:    case NETCONN_UDPLITE:
326    case NETCONN_UDPNOCHKSUM:    case NETCONN_UDPNOCHKSUM:
327    case NETCONN_UDP:    case NETCONN_UDP:
# Line 342  netconn_bind(struct netconn *conn, struc Line 342  netconn_bind(struct netconn *conn, struc
342  {  {
343    struct api_msg *msg;    struct api_msg *msg;
344    
345    if(conn == NULL) {    if (conn == NULL) {
346      return ERR_VAL;      return ERR_VAL;
347    }    }
348    
349    if(conn->type != NETCONN_TCP &&    if (conn->type != NETCONN_TCP &&
350       conn->recvmbox == SYS_MBOX_NULL) {       conn->recvmbox == SYS_MBOX_NULL) {
351      if((conn->recvmbox = sys_mbox_new()) == SYS_MBOX_NULL) {      if ((conn->recvmbox = sys_mbox_new()) == SYS_MBOX_NULL) {
352        return ERR_MEM;        return ERR_MEM;
353      }      }
354    }    }
355        
356    if((msg = memp_mallocp(MEMP_API_MSG)) == NULL) {    if ((msg = memp_mallocp(MEMP_API_MSG)) == NULL) {
357      return (conn->err = ERR_MEM);      return (conn->err = ERR_MEM);
358    }    }
359    msg->type = API_MSG_BIND;    msg->type = API_MSG_BIND;
# Line 373  netconn_connect(struct netconn *conn, st Line 373  netconn_connect(struct netconn *conn, st
373  {  {
374    struct api_msg *msg;    struct api_msg *msg;
375        
376    if(conn == NULL) {    if (conn == NULL) {
377      return ERR_VAL;      return ERR_VAL;
378    }    }
379    
380    
381    if(conn->recvmbox == SYS_MBOX_NULL) {    if (conn->recvmbox == SYS_MBOX_NULL) {
382      if((conn->recvmbox = sys_mbox_new()) == SYS_MBOX_NULL) {      if ((conn->recvmbox = sys_mbox_new()) == SYS_MBOX_NULL) {
383        return ERR_MEM;        return ERR_MEM;
384      }      }
385    }    }
386        
387    if((msg = memp_mallocp(MEMP_API_MSG)) == NULL) {    if ((msg = memp_mallocp(MEMP_API_MSG)) == NULL) {
388      return ERR_MEM;      return ERR_MEM;
389    }    }
390    msg->type = API_MSG_CONNECT;    msg->type = API_MSG_CONNECT;
# Line 402  netconn_disconnect(struct netconn *conn) Line 402  netconn_disconnect(struct netconn *conn)
402  {  {
403    struct api_msg *msg;    struct api_msg *msg;
404        
405    if(conn == NULL) {    if (conn == NULL) {
406      return ERR_VAL;      return ERR_VAL;
407    }    }
408    
409    if((msg = memp_mallocp(MEMP_API_MSG)) == NULL) {    if ((msg = memp_mallocp(MEMP_API_MSG)) == NULL) {
410      return ERR_MEM;      return ERR_MEM;
411    }    }
412    msg->type = API_MSG_DISCONNECT;    msg->type = API_MSG_DISCONNECT;
# Line 423  netconn_listen(struct netconn *conn) Line 423  netconn_listen(struct netconn *conn)
423  {  {
424    struct api_msg *msg;    struct api_msg *msg;
425    
426    if(conn == NULL) {    if (conn == NULL) {
427      return ERR_VAL;      return ERR_VAL;
428    }    }
429    
430    if(conn->acceptmbox == SYS_MBOX_NULL) {    if (conn->acceptmbox == SYS_MBOX_NULL) {
431      conn->acceptmbox = sys_mbox_new();      conn->acceptmbox = sys_mbox_new();
432      if(conn->acceptmbox == SYS_MBOX_NULL) {      if (conn->acceptmbox == SYS_MBOX_NULL) {
433        return ERR_MEM;        return ERR_MEM;
434      }      }
435    }    }
436        
437    if((msg = memp_mallocp(MEMP_API_MSG)) == NULL) {    if ((msg = memp_mallocp(MEMP_API_MSG)) == NULL) {
438      return (conn->err = ERR_MEM);      return (conn->err = ERR_MEM);
439    }    }
440    msg->type = API_MSG_LISTEN;    msg->type = API_MSG_LISTEN;
# Line 450  netconn_accept(struct netconn *conn) Line 450  netconn_accept(struct netconn *conn)
450  {  {
451    struct netconn *newconn;    struct netconn *newconn;
452        
453    if(conn == NULL) {    if (conn == NULL) {
454      return NULL;      return NULL;
455    }    }
456        
# Line 470  netconn_recv(struct netconn *conn) Line 470  netconn_recv(struct netconn *conn)
470    struct pbuf *p;    struct pbuf *p;
471    u16_t len;    u16_t len;
472            
473    if(conn == NULL) {    if (conn == NULL) {
474      return NULL;      return NULL;
475    }    }
476        
477    if(conn->recvmbox == SYS_MBOX_NULL) {    if (conn->recvmbox == SYS_MBOX_NULL) {
478      conn->err = ERR_CONN;      conn->err = ERR_CONN;
479      return NULL;      return NULL;
480    }    }
481    
482    if(conn->err != ERR_OK) {    if (conn->err != ERR_OK) {
483      return NULL;      return NULL;
484    }    }
485    
486    if(conn->type == NETCONN_TCP) {    if (conn->type == NETCONN_TCP) {
487      if(conn->pcb.tcp->state == LISTEN) {      if (conn->pcb.tcp->state == LISTEN) {
488        conn->err = ERR_CONN;        conn->err = ERR_CONN;
489        return NULL;        return NULL;
490      }      }
# Line 492  netconn_recv(struct netconn *conn) Line 492  netconn_recv(struct netconn *conn)
492    
493      buf = memp_mallocp(MEMP_NETBUF);      buf = memp_mallocp(MEMP_NETBUF);
494    
495      if(buf == NULL) {      if (buf == NULL) {
496        conn->err = ERR_MEM;        conn->err = ERR_MEM;
497        return NULL;        return NULL;
498      }      }
# Line 513  netconn_recv(struct netconn *conn) Line 513  netconn_recv(struct netconn *conn)
513    
514      /* If we are closed, we indicate that we no longer wish to recieve      /* If we are closed, we indicate that we no longer wish to recieve
515         data by setting conn->recvmbox to SYS_MBOX_NULL. */         data by setting conn->recvmbox to SYS_MBOX_NULL. */
516      if(p == NULL) {      if (p == NULL) {
517        memp_freep(MEMP_NETBUF, buf);        memp_freep(MEMP_NETBUF, buf);
518        sys_mbox_free(conn->recvmbox);        sys_mbox_free(conn->recvmbox);
519        conn->recvmbox = SYS_MBOX_NULL;        conn->recvmbox = SYS_MBOX_NULL;
# Line 526  netconn_recv(struct netconn *conn) Line 526  netconn_recv(struct netconn *conn)
526      buf->fromaddr = NULL;      buf->fromaddr = NULL;
527    
528      /* Let the stack know that we have taken the data. */      /* Let the stack know that we have taken the data. */
529      if((msg = memp_mallocp(MEMP_API_MSG)) == NULL) {      if ((msg = memp_mallocp(MEMP_API_MSG)) == NULL) {
530        conn->err = ERR_MEM;        conn->err = ERR_MEM;
531        return buf;        return buf;
532      }      }
533      msg->type = API_MSG_RECV;      msg->type = API_MSG_RECV;
534      msg->msg.conn = conn;      msg->msg.conn = conn;
535      if(buf != NULL) {      if (buf != NULL) {
536        msg->msg.msg.len = buf->p->tot_len;        msg->msg.msg.len = buf->p->tot_len;
537      } else {      } else {
538        msg->msg.msg.len = 1;        msg->msg.msg.len = 1;
# Line 563  netconn_send(struct netconn *conn, struc Line 563  netconn_send(struct netconn *conn, struc
563  {  {
564    struct api_msg *msg;    struct api_msg *msg;
565    
566    if(conn == NULL) {    if (conn == NULL) {
567      return ERR_VAL;      return ERR_VAL;
568    }    }
569    
570    if(conn->err != ERR_OK) {    if (conn->err != ERR_OK) {
571      return conn->err;      return conn->err;
572    }    }
573    
574    if((msg = memp_mallocp(MEMP_API_MSG)) == NULL) {    if ((msg = memp_mallocp(MEMP_API_MSG)) == NULL) {
575      return (conn->err = ERR_MEM);      return (conn->err = ERR_MEM);
576    }    }
577    
# Line 592  netconn_write(struct netconn *conn, void Line 592  netconn_write(struct netconn *conn, void
592    struct api_msg *msg;    struct api_msg *msg;
593    u16_t len;    u16_t len;
594        
595    if(conn == NULL) {    if (conn == NULL) {
596      return ERR_VAL;      return ERR_VAL;
597    }    }
598    
599    if(conn->err != ERR_OK) {    if (conn->err != ERR_OK) {
600      return conn->err;      return conn->err;
601    }    }
602        
603    if(conn->sem == SYS_SEM_NULL) {    if (conn->sem == SYS_SEM_NULL) {
604      conn->sem = sys_sem_new(0);      conn->sem = sys_sem_new(0);
605      if(conn->sem == SYS_SEM_NULL) {      if (conn->sem == SYS_SEM_NULL) {
606        return ERR_MEM;        return ERR_MEM;
607      }      }
608    }    }
609    
610    if((msg = memp_mallocp(MEMP_API_MSG)) == NULL) {    if ((msg = memp_mallocp(MEMP_API_MSG)) == NULL) {
611      return (conn->err = ERR_MEM);      return (conn->err = ERR_MEM);
612    }    }
613    msg->type = API_MSG_WRITE;    msg->type = API_MSG_WRITE;
# Line 615  netconn_write(struct netconn *conn, void Line 615  netconn_write(struct netconn *conn, void
615                    
616    
617    conn->state = NETCONN_WRITE;    conn->state = NETCONN_WRITE;
618    while(conn->err == ERR_OK && size > 0) {    while (conn->err == ERR_OK && size > 0) {
619      msg->msg.msg.w.dataptr = dataptr;      msg->msg.msg.w.dataptr = dataptr;
620      msg->msg.msg.w.copy = copy;      msg->msg.msg.w.copy = copy;
621            
622      if(conn->type == NETCONN_TCP) {      if (conn->type == NETCONN_TCP) {
623        if(tcp_sndbuf(conn->pcb.tcp) == 0) {        if (tcp_sndbuf(conn->pcb.tcp) == 0) {
624          sys_sem_wait(conn->sem);          sys_sem_wait(conn->sem);
625          if(conn->err != ERR_OK) {          if (conn->err != ERR_OK) {
626            goto ret;            goto ret;
627          }          }
628        }        }
629        if(size > tcp_sndbuf(conn->pcb.tcp)) {        if (size > tcp_sndbuf(conn->pcb.tcp)) {
630          /* We cannot send more than one send buffer's worth of data at a          /* We cannot send more than one send buffer's worth of data at a
631             time. */             time. */
632          len = tcp_sndbuf(conn->pcb.tcp);          len = tcp_sndbuf(conn->pcb.tcp);
# Line 641  netconn_write(struct netconn *conn, void Line 641  netconn_write(struct netconn *conn, void
641      msg->msg.msg.w.len = len;      msg->msg.msg.w.len = len;
642      api_msg_post(msg);      api_msg_post(msg);
643      sys_mbox_fetch(conn->mbox, NULL);          sys_mbox_fetch(conn->mbox, NULL);    
644      if(conn->err == ERR_OK) {      if (conn->err == ERR_OK) {
645        dataptr = (void *)((char *)dataptr + len);        dataptr = (void *)((char *)dataptr + len);
646        size -= len;        size -= len;
647      } else if(conn->err == ERR_MEM) {      } else if (conn->err == ERR_MEM) {
648        conn->err = ERR_OK;        conn->err = ERR_OK;
649        sys_sem_wait(conn->sem);        sys_sem_wait(conn->sem);
650      } else {      } else {
# Line 654  netconn_write(struct netconn *conn, void Line 654  netconn_write(struct netconn *conn, void
654   ret:   ret:
655    memp_freep(MEMP_API_MSG, msg);    memp_freep(MEMP_API_MSG, msg);
656    conn->state = NETCONN_NONE;    conn->state = NETCONN_NONE;
657    if(conn->sem != SYS_SEM_NULL) {    if (conn->sem != SYS_SEM_NULL) {
658      sys_sem_free(conn->sem);      sys_sem_free(conn->sem);
659      conn->sem = SYS_SEM_NULL;      conn->sem = SYS_SEM_NULL;
660    }    }
# Line 667  netconn_close(struct netconn *conn) Line 667  netconn_close(struct netconn *conn)
667  {  {
668    struct api_msg *msg;    struct api_msg *msg;
669    
670    if(conn == NULL) {    if (conn == NULL) {
671      return ERR_VAL;      return ERR_VAL;
672    }    }
673    if((msg = memp_mallocp(MEMP_API_MSG)) == NULL) {    if ((msg = memp_mallocp(MEMP_API_MSG)) == NULL) {
674      return (conn->err = ERR_MEM);      return (conn->err = ERR_MEM);
675    }    }
676    
# Line 680  netconn_close(struct netconn *conn) Line 680  netconn_close(struct netconn *conn)
680    msg->msg.conn = conn;    msg->msg.conn = conn;
681    api_msg_post(msg);    api_msg_post(msg);
682    sys_mbox_fetch(conn->mbox, NULL);    sys_mbox_fetch(conn->mbox, NULL);
683    if(conn->err == ERR_MEM &&    if (conn->err == ERR_MEM &&
684       conn->sem != SYS_SEM_NULL) {       conn->sem != SYS_SEM_NULL) {
685      sys_sem_wait(conn->sem);      sys_sem_wait(conn->sem);
686      goto again;      goto again;

Legend:
Removed from v.1.11.2.1  
changed lines
  Added in v.1.11.2.2

savannah-hackers-public@gnu.org
ViewVC Help
Powered by ViewVC 1.1.26