lua-users home
lua-l archive

[Date Prev][Date Next][Thread Prev][Thread Next] [Date Index] [Thread Index]


Hi,

On 7/20/06, Diego Nehab <diego@tecgraf.puc-rio.br> wrote:
> 1) It would be great if your build process could support being built
> directly into the interpreter. My system doesn't have dynamic linking,
> so I had to hack your Makefiles (needed in any way, because the
> compiler flags have to be <just so> to get it to actually run on the
> target system).

You mean automatically? This is tough, isn't it? You have to
change your interpreter, and LuaSocket doesn't have access
to it. If you are building your own interpreter, on the
otherh and, it is simple to link LuaSocket to it.

Just add the obj files to your makefile, then make sure you
populate package.preload with luaopen_socket_core and
luaopen_mime_core.

It is not about being tough or not. It's a simple request that at
least have an option to be friendly to those who are building your
code directly into the interpreter. It shouldn't be a large change to
the makefile.

Here's the diff from my makefile to yours (src/makefile). I had to
create a config file that had the same parameters etc as I used to
build my Lua interpreter.

--- /opt/pose/bin/luasocket-2.0.1/src/makefile	2006-04-27
03:23:21.000000000 +0000
+++ makefile	2006-07-08 09:00:09.000000000 +0000
@@ -1,7 +1,7 @@
#------
# Load configuration
#
-include ../config
+include config

#------
# Hopefully no need to change anything below this line
@@ -12,7 +12,6 @@
#

SOCKET_OBJS:= \
-	$(COMPAT)/compat-5.1.o \
	luasocket.o \
	timeout.o \
	buffer.o \
@@ -30,7 +29,6 @@
# Modules belonging mime-core
#
MIME_OBJS:=\
-	$(COMPAT)/compat-5.1.o \
	mime.o


@@ -46,16 +44,24 @@
	usocket.o \
	unix.o

-all: $(SOCKET_SO) $(MIME_SO)
+EXPORT_SO=luasocket.a
+SOCKET_SO=socket.a
+MIME_SO=mime.a
+UNIX_SO=unix.a
+
+all: $(SOCKET_SO) $(MIME_SO)  $(EXPORT_SO)
+
+$(EXPORT_SO): $(SOCKET_OBJS) $(MIME_SO)
+	$(AR) $(EXPORT_SO) $(SOCKET_OBJS) $(MIME_OBJS)

$(SOCKET_SO): $(SOCKET_OBJS)
-	$(LD) $(LDFLAGS) -o $@ $(SOCKET_OBJS)
+	$(AR) $(SOCKET_SO) $(SOCKET_OBJS)

$(MIME_SO): $(MIME_OBJS)
-	$(LD) $(LDFLAGS) -o $@ $(MIME_OBJS)
+	$(AR) $(MIME_SO) $(MIME_OBJS)

$(UNIX_SO): $(UNIX_OBJS)
-	$(LD) $(LDFLAGS) -o $@ $(UNIX_OBJS)
+	$(AR) $(UNIX_SO) $@ $(UNIX_OBJS)

#------
# List of dependencies


> 3) It doesn't have ping functionality, though it wouldn't be hard to
> do that, but why not? Pings that timeout are basically the only way I
> can think of to check if the network is available or not.

I'd be happy to consider a patch for that. I believe it
would require an API and some C code.

Here's some C code for that. It's derived from BusyBox ping (socket
timeout and not lingering added). The rest I found were quite bloated.
I'm sure you can work from it.

#define DEFDATALEN      56
#define	MAXIPLEN	60
#define	MAXICMPLEN	76

static int ping(lua_State *L)
{
	struct hostent *h;
	struct sockaddr_in pingaddr;
	struct icmp *pkt;
	struct timeval timeout;
	struct linger linger;
	int pingsock, c, secs, ret;
	const char *host;
	char packet[DEFDATALEN + MAXIPLEN + MAXICMPLEN];

	host = lua_tostring(L, 1);
	secs = (int) lua_tonumber(L, 2);

	if ((pingsock = socket(AF_INET, SOCK_RAW, 1)) < 0) {	/* 1 == ICMP */
		goto notreachable;
	}

	memset(&pingaddr, 0, sizeof(struct sockaddr_in));
	pingaddr.sin_family = AF_INET;	
	
	if (!(h = gethostbyname(host)))
		goto notreachable;
	
	memcpy(&pingaddr.sin_addr, h->h_addr, sizeof(pingaddr.sin_addr));

	pkt = (struct icmp *) packet;
	memset(pkt, 0, sizeof(packet));
	pkt->icmp_type = ICMP_ECHO;
	pkt->icmp_cksum = in_cksum((unsigned short *) pkt, sizeof(packet));

	/* set timeout to user supplied value */
	timeout.tv_sec = secs;
	timeout.tv_usec = 0;

	/* set socket to linger for user supplied time */
	linger.l_onoff = 1;
	linger.l_linger = secs;
	
   if (setsockopt (pingsock, SOL_SOCKET, SO_LINGER, (char *)&linger,
sizeof linger) < 0)
		goto notreachable;
	if (setsockopt (pingsock, SOL_SOCKET, SO_RCVTIMEO, (char *)&timeout,
sizeof timeout) < 0)
		goto notreachable;
	if (setsockopt (pingsock, SOL_SOCKET, SO_SNDTIMEO, (char *)&timeout,
sizeof timeout) < 0)
		goto notreachable;

	c = sendto(pingsock, packet, sizeof(packet), 0,
			   (struct sockaddr *) &pingaddr, sizeof(struct sockaddr_in));
	if (c < 0 || c != sizeof(packet))
		goto notreachable;

	/* listen for replies */
	while (1) {
		struct sockaddr_in from;
		socklen_t fromlen = sizeof(from);
		if ((c = recvfrom (pingsock, packet, sizeof(packet), 0,
						  (struct sockaddr *) &from, (socklen_t *)&fromlen )) < 0) {
			if(errno == EAGAIN || errno == ETIMEDOUT)
				goto notreachable;
			else
				continue;
		}
		if (c >= 76) {			/* ip + icmp */
			struct iphdr *iphdr = (struct iphdr *) packet;

			pkt = (struct icmp *) (packet + (iphdr->ihl << 2));	/* skip ip hdr */
			if (pkt->icmp_type == ICMP_ECHOREPLY)
				break;
		}
	}
	
	close(pingsock);
	lua_pushboolean(L, 1);
	return 1;
	
notreachable:
	ret = pusherror(L, NULL);
	close(pingsock);
	return ret;
}

static int in_cksum(unsigned short *buf, int sz)
{
	int nleft = sz;
	int sum = 0;
	unsigned short *w = buf;
	unsigned short ans = 0;

	while (nleft > 1) {
		sum += *w++;
		nleft -= 2;
	}

	if (nleft == 1) {
		*(unsigned char *) (&ans) = *(unsigned char *) w;
		sum += ans;
	}

	sum = (sum >> 16) + (sum & 0xFFFF);
	sum += (sum >> 16);
	ans = ~sum;
	return (ans);
}

> I implemented my own (basic!) HTTP client instead. It fetches from a
> URL and returns the response minus headers. Here's the implementation
> (sans libhttpd which is a socket object built into the interpreter).

If you are interested in the lowest possible number of lines
of code, I would suggest using popen and wget...

It's not the lowest number of lines. I'm building for a embedded
system. Your library alone is bigger than my entire application
(including the functionality that I wanted from your library).

Is that too hard to understand?

-- G.