#include "lwip/tcp.h"
static err_t server_accept(void *arg, struct tcp_pcb *pcb, err_t err);
static err_t server_recv(void *arg, struct tcp_pcb *pcb, struct pbuf *p,
err_t err);
static err_t server_poll(void *arg, struct tcp_pcb *pcb);
static err_t server_err(void *arg, err_t err);
void my_server_init(void)
{
struct tcp_pcb *pcb;
pcb = tcp_new();
tcp_bind(pcb, IP_ADDR_ANY, 8000); //server port for incoming connection
pcb = tcp_listen(pcb);
tcp_accept(pcb, server_accept);
}
static void server_close(struct tcp_pcb *pcb)
{
tcp_arg(pcb, NULL);
tcp_sent(pcb, NULL);
tcp_recv(pcb, NULL);
tcp_close(pcb);
printf("\nserver_close(): Closing...\n");
}
static err_t server_accept(void *arg, struct tcp_pcb *pcb, err_t err)
{
LWIP_UNUSED_ARG(arg);
LWIP_UNUSED_ARG(err);
tcp_setprio(pcb, TCP_PRIO_MIN);
tcp_arg(pcb, NULL);
tcp_recv(pcb, server_recv);
tcp_err(pcb, server_err);
tcp_poll(pcb, server_poll, 4); //every two seconds of inactivity of
the TCP connection
tcp_accepted(pcb);
printf("\nserver_accept(): Accepting incoming connection on
server...\n");
return ERR_OK;
}
static err_t server_recv(void *arg, struct tcp_pcb *pcb, struct pbuf *p,
err_t err)
{
char *string;
int length;
LWIP_UNUSED_ARG(arg);
if (err == ERR_OK && p != NULL)
{
tcp_recved(pcb, p->tot_len);
string = p->payload;
length = strlen(string);
printf("\nserver_recv(): Incoming string is %s\n", string);
printf("\nserver_recv(): String length is %d byte\n", length);
printf("server_recv(): pbuf->len is %d byte\n", p->len);
printf("server_recv(): pbuf->tot_len is %d byte\n", p->tot_len);
printf("server_recv(): pbuf->next is %d\n", p->next);
pbuf_free(p);
server_close(pcb);
}
else
{
printf("\nserver_recv(): Errors-> ");
if (err != ERR_OK)
printf("1) Connection is not on ERR_OK state, but in %d
state->\n", err);
if (p == NULL)
printf("2) Pbuf pointer p is a NULL pointer->\n ");
printf("server_recv(): Closing server-side connection...");
pbuf_free(p);
server_close(pcb);
}
return ERR_OK;
}
static err_t server_sent(void *arg, struct tcp_pcb *pcb, u16_t len)
{
LWIP_UNUSED_ARG(len);
LWIP_UNUSED_ARG(arg);
printf("\nserver_sent(): Correctly ACK'ed, closing server-side
connection...\n");
server_close(pcb);
return ERR_OK;
}
static err_t server_poll(void *arg, struct tcp_pcb *pcb)
{
static int counter = 1;
LWIP_UNUSED_ARG(arg);
LWIP_UNUSED_ARG(pcb);
printf("\nserver_poll(): Call number %d\n", counter++);
return ERR_OK;
}
static err_t server_err(void *arg, err_t err)
{
LWIP_UNUSED_ARG(arg);
LWIP_UNUSED_ARG(err);
printf("\nserver_err(): Fatal error, exiting...\n");
return ERR_OK;
}
Now i'm trying to create the client. But the communication between the
processes doesn't work: the client send the SYN segment but never
receives an answer, and the server never receives the connection request
from the client. I've built the server process giving it the address
192.168.1.200 and the client process with 192.168.1.201. They are
separate processes on the same machine but they use the same network
adapter. Here it is the code for the client:
static err_t client_sent(void *arg, struct tcp_pcb *pcb, u16_t len);
static err_t client_connected(void *arg, struct tcp_pcb *pcb, err_t err);
void my_client_init(void)
{
struct tcp_pcb *pcb;
struct ip_addr dest;
err_t ret_val;
IP4_ADDR(&dest, 192, 168, 1, 200);
pcb = tcp_new();
tcp_bind(pcb, IP_ADDR_ANY, 7000); //client port for outcoming connection
tcp_arg(pcb, NULL);
ret_val = tcp_connect(pcb, &dest, 8000, client_connected); //server
port for incoming connection
if (ret_val != ERR_OK)
printf("\tcp_connect(): Errors on return value, returned value
is %d\n", ret_val);
}
static void client_close(struct tcp_pcb *pcb)
{
tcp_arg(pcb, NULL);
tcp_sent(pcb, NULL);
tcp_close(pcb);
printf("\nclient_close(): Closing...\n");
}
static err_t client_connected(void *arg, struct tcp_pcb *pcb, err_t err)
{
char *string = "Hello!";
LWIP_UNUSED_ARG(arg);
if (err != ERR_OK)
printf("\nclient_connected(): err argument not set to ERR_OK,
but is value is %d\n", err);
else
{
tcp_sent(pcb, client_sent);
tcp_write(pcb, string, sizeof(string), 0);
}
return err;
}
static err_t client_sent(void *arg, struct tcp_pcb *pcb, u16_t len)
{
LWIP_UNUSED_ARG(arg);
printf("\nclient_sent(): Number of bytes ACK'ed is %d", len);
client_close(pcb);
return ERR_OK;
}
I'm using the test.c file "model" to build my applications: I've
removed from the test application all the code which I don't need and
then I've introduced the source code written for my applications. I use
the same test.c for both the client and server, compiling it with
my_client_init(); or my_server_init() for the client or the server. So
the code for test.c file (containing the main()) is this:
/* C runtime includes */
#include <stdio.h>
#include <stdarg.h>
#include <time.h>
#include <string.h>
#include <conio.h>
/* lwIP core includes */
#include "lwip/opt.h"
#include "lwip/init.h"
#include "lwip/tcp.h"
/* lwIP netif includes */
#include "netif/etharp.h"
/* applications includes */
/*
#include "server.h"
#include "client.h"
*/
void my_server_init(void);
void my_client_init(void);
/* NO_SYS == 1: we need information about the timer intervals: */
#include "lwip/ip_frag.h"
#include "lwip/igmp.h"
/* ethernet layer include */
#include "pktif.h"
/* include the port-dependent configuration */
#include "lwipcfg_msvc.h"
/* port-defined functions used for timer execution, defined in sys_arch.c */
void sys_init_timing();
u32_t sys_now();
/* globales variables for netifs */
/* THE ethernet interface */
struct netif netif;
/* special functions used for NO_SYS==1 only */
typedef struct _timers_infos
{
int timer;
int timer_interval;
void (*timer_func)(void);
} timers_infos;
static timers_infos timers_table[] =
{
{ 0, TCP_FAST_INTERVAL, tcp_fasttmr},
{ 0, TCP_SLOW_INTERVAL, tcp_slowtmr},
{ 0, ARP_TMR_INTERVAL, etharp_tmr},
{ 0, IGMP_TMR_INTERVAL, igmp_tmr},
{ 0, IP_TMR_INTERVAL, ip_reass_tmr},
};
/* get the current time and see if any timer has expired */
static void timers_update()
{
/* static variables for timer execution, initialized to zero! */
static int last_time;
int cur_time, time_diff, idxtimer;
cur_time = sys_now();
time_diff = cur_time - last_time;
/* the '> 0' is an easy wrap-around check: the big gap at
* the wraparound step is simply ignored... */
if (time_diff > 0)
{
last_time = cur_time;
for( idxtimer=0;
idxtimer<(sizeof(timers_table)/sizeof(timers_infos)); idxtimer++)
{
timers_table[idxtimer].timer += time_diff;
if (timers_table[idxtimer].timer >
timers_table[idxtimer].timer_interval)
{
timers_table[idxtimer].timer_func();
timers_table[idxtimer].timer -=
timers_table[idxtimer].timer_interval;
}
}
}
}
void status_callback(struct netif *netif)
{
if (netif_is_up(netif))
{
printf("status_callback==UP, local interface IP is %s\n",
inet_ntoa(*(struct in_addr*)&(netif->ip_addr)));
}
else
{
printf("status_callback==DOWN\n");
}
}
void link_callback(struct netif *netif)
{
if (netif_is_link_up(netif))
{
printf("link_callback==UP\n");
}
else
{
printf("link_callback==DOWN\n");
}
}
/* This function initializes all network interfaces */
static void msvc_netif_init()
{
struct ip_addr ipaddr, netmask, gw;
LWIP_PORT_INIT_GW(&gw);
LWIP_PORT_INIT_IPADDR(&ipaddr);
LWIP_PORT_INIT_NETMASK(&netmask);
printf("Starting lwIP, local interface IP is %s\n",
inet_ntoa(*(struct in_addr*)&ipaddr));
netif_set_default(netif_add(&netif, &ipaddr, &netmask, &gw, NULL,
ethernetif_init, ethernet_input));
netif_set_status_callback(&netif, status_callback);
netif_set_link_callback(&netif, link_callback);
netif_set_up(&netif);
}
void main_loop()
{
/* initialize lwIP stack, network interfaces and application */
sys_init_timing();
lwip_init();
/* init network interfaces */
msvc_netif_init();
/* init application */
//my_server_init(); /* My Server */
my_client_init(); /* My Client */
/* MAIN LOOP for driver update (and timers if NO_SYS) */
while (!_kbhit())
{
/* handle timers (already done in tcpip.c when NO_SYS=0) */
timers_update();
/* check for packets and link status*/
ethernetif_poll(&netif);
/* check for loopback packets on all netifs */
netif_poll_all();
}
/* release the pcap library... */
ethernetif_shutdown(&netif);
}
int main(void)
{
/* no stdio-buffering, please! */
setvbuf(stdout, NULL,_IONBF, 0);
main_loop();
return 0;
}
I hope that someone can help me, I don't know why the communication
doesn't work, I can't understand! Thank you Bye!
Antonio de Angelis
_______________________________________________
lwip-users mailing list
lwip-...@nongnu.org
http://lists.nongnu.org/mailman/listinfo/lwip-users
As to your problem: I don't really know why this doesn't work, I already
did such a setup on my PC. Did you try your client application to
connect to some other (non lwIP) server? Maybe even outside your PC? If
you still have problems, you can try to use wireshark to monitor the
ethernet packets sent on the network. Maybe that helps to find the problem.
Simon
Antonio de Angelis
gold...@gmx.de ha scritto:
Antonio de Angelis
gold...@gmx.de ha scritto:
The problem here is likely to be the routing table. When sending a
packet lwIP searches through the list of netifs and compares the IP
address of the interface with the destination address of the packet. If
none of them match it will use the default, which is usually to send it
out onto the network.
I'm guessing that you have two different processes, and so two separate
instances of lwIP for your client and server. Do they share a driver?
Do they share a network card? Assuming they are structured like this,
it would mean that they would each have a separate routing table and not
know that the other is local. They would therefore send packets that
should go to the other one out on to the network.
You need something, either in the network, or a software bridge, that
will know that they are both on the same machine and route the packets
back again. On Linux it is relatively easy to set up a software bridge
to do this, but I'm not sure how you would do it on Windows.
Kieran
Simon
In Settings -> Network Connections select 2 (or more) connections (with the
Ctrl key) and right click the selection and choose Bridge Connections.
Bill
Simon
> ------------------------------------------------------------------------
Antonio de Angelis
-----Messaggio originale-----
Da: lwip-users-bounces+finalvengeance=tisca...@nongnu.org
[mailto:lwip-users-bounces+finalvengeance=tisca...@nongnu.org] Per conto
di gold...@gmx.de
Inviato: mercoledì 9 luglio 2008 21.00
A: Mailing list for lwIP users
Oggetto: Re: [lwip-users] How to build a simple TCP [...]
This issue is completely handled in pktif.c: the netif's MAC is assigned there by simply adding 1 + lwIP's netif index to that last octet of the mac (which is done in line 131).
If your PC's MAC address is 01:02:03:04:05:06, lwIP will take 01:02:03:04:05:07 for its first pktif driver running on that ethernet card (or :08 if you also use the loopif). However, the other instances of lwIP (running in their own process) do the same, so all instances of lwIP use the same MAC address. What you would have to do is to make the first instance of lwIP use a different MAC than the second. But since this is difficult to do, this has not been done in CVS (yet?). For example, you could take the process ID and add it as an offset...
Simon
-------- Original-Nachricht --------
> Datum: Thu, 10 Jul 2008 09:57:34 +0200
> Von: "Antonio de Angelis" <finalve...@tiscali.it>
> An: "\'Mailing list for lwIP users\'" <lwip-...@nongnu.org>
> Betreff: Re: [lwip-users] How to build a simple TCP [...]
--
Ist Ihr Browser Vista-kompatibel? Jetzt die neuesten
Browser-Versionen downloaden: http://www.gmx.net/de/go/browser
Yikes! We should document that more obviously, as it's something that
people will likely want to change to be more robust.
Kieran
Simon
-------- Original-Nachricht --------
> Datum: Thu, 10 Jul 2008 09:52:14 +0100
> Von: Kieran Mansley <kie...@recoil.org>
> An: Mailing list for lwIP users <lwip-...@nongnu.org>
> Betreff: Re: [lwip-users] How to build a simple TCP [...]
> On Thu, 2008-07-10 at 10:41 +0200, Simon Goldschmidt wrote:
--
GMX startet ShortView.de. Hier findest Du Leute mit Deinen Interessen!
Jetzt dabei sein: http://www.shortview.de/wasistshortview.php?mc=sv_ext_mf@gmx
I think that would be better. It would make it more obvious that the
MAC address being used is just made up, and so needs to be carefully
chosen.
Simon.
> ------------------------------------------------------------------------
Simon
The specs also say that there are some bits in the first two bytes of
the MAC that need to be set when it is a virtual NIC instead of a real
card. I have implemented that at work for emulations using tap devices
on FreeBSD, but don't have the reference here at home.
Bob McConnell
N2SPP
The second bit transmitted in the first octet of the MAC address identifies
the address as "locally administered".
This corresponds to a value of 02 in the first octet when it is written in
the usual MSB first order, so an example of a locally administered address
would be 02-01-02-03-04-05.
The first octet can have any even value (bit 0 must not be set, because that
would identify it as a group address, i.e. broadcast/multicast). The other
five octets can be anything.
http://standards.ieee.org/regauth/groupmac/tutorial.html
http://en.wikipedia.org/wiki/MAC_address
A locally administered address cannot be allocated by a manufacturer to any
production Ethernet hardware, but can be used by network administrators to
assign arbitrary MAC addresses for use within their organisation.
Since locally administered MAC addresses are potentially being reused by
multiple people, if LWIP picks an arbitrary one it may have a greater chance
of encountering a conflict. If LWIP "borrows" an arbitrary universally
administered MAC address, there can be only one conflicting device in the
whole world.
I suggest using a locally administered address anyway, but it should be well
commented to explain the potential for a conflict, and summarise the rules
for allocating a different MAC address, in particular not to use an odd
value for the first octet (broadcast/multicast).