unofficial mirror of guile-user@gnu.org 
 help / color / mirror / Atom feed
* Trouble w/sockets
@ 2013-03-03  3:38 mark
  2013-03-03  4:48 ` Mike Gran
  0 siblings, 1 reply; 10+ messages in thread
From: mark @ 2013-03-03  3:38 UTC (permalink / raw)
  To: guile-user


Hi all,

I've made lots of progress on my Guile xcb code and it talks to the X
server now, send requests, receive replies and so forth.

However, if the X server requires authentication, there's trouble. I'm
able to send the authentication method's name over the socket that
connects to the X server, but as soon as I try to send the first byte of
the authentication value, Guile crashes.

This code should hopefully reproduce the issue (assuming you're on a
little-endian system and have an X server listening at the given
socket). The segment of data starting with 77 is the authentication
method's name; then there's an equally long sequence of zeros and the
remaining numbers are the authentication value and some more padding.

(define sock (socket AF_UNIX SOCK_STREAM 0))
(connect sock (make-socket-address AF_UNIX "/tmp/.X11-unix/X0"))
(for-each      
  (lambda (b)
    (write-char (integer->char b) sock))
      '(108 0 11 0 0 0 18 0 16 0 0 0 77 73 84 45 77 65 71 73 67 45 67 79
      79 75 73 69 45 49 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 243 236 56
      103 158 249 237 124 101 131 158 31 63 251 239 7 0 0 0 0 0 0 0 0 0
      0 0 0 0 0 0 0))

This will obviously be the wrong authentication data for anyone else's X
server; however, even if X closes the socket prematurely (not that it's
supposed to, but it might), Guile shouldn't just crash, should it?

Thanks

-- 
Mark Witmer



^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: Trouble w/sockets
  2013-03-03  3:38 Trouble w/sockets mark
@ 2013-03-03  4:48 ` Mike Gran
  2013-03-03  5:36   ` mark
  2013-03-03 10:36   ` Chris Vine
  0 siblings, 2 replies; 10+ messages in thread
From: Mike Gran @ 2013-03-03  4:48 UTC (permalink / raw)
  To: mark@markwitmer.com, guile-user@gnu.org

> From: "mark@markwitmer.com" <mark@markwitmer.com>

> (for-each      
>   (lambda (b)
>     (write-char (integer->char b) sock))
>       '(108 0 11 0 0 0 18 0 16 0 0 0 77 73 84 45 77 65 71 73 67 45 67 79
>       79 75 73 69 45 49 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 243 236 56
>       103 158 249 237 124 101 131 158 31 63 251 239 7 0 0 0 0 0 0 0 0 0
>       0 0 0 0 0 0 0))
> 
> This will obviously be the wrong authentication data for anyone else's X
> server; however, even if X closes the socket prematurely (not that it's
> supposed to, but it might), Guile shouldn't just crash, should it?

Crash? Or throw an error?  I definitely shouldn't crash, but, I could see
how it could throw an error on Guile 2.0.

The problem with `write-char' in Guile 2.0 is that it does all the
conversion to the current locale.  So, once you start hitting the bytes
greater than 127 in your string, `write-char' tries to convert each
byte to something in your encoding.

If your encoding is "C" or anything that strictly uses ASCII as its
character encoding, it'll throw an error when its trying to print any
byte above 127.  If your encoding is UTF-8, those high bytes will become
two byte strings.

Ideally you'd be able to use bytevectors or binary ports or some such.

But you can also fake it by setting the port encoding to ISO-8859-1.
In that encoding the characters 0 to 255 map one-to-one with the bytes
from 0 to 255.
(set-port-encoding! sock "ISO-8859-1")

Hope this helps,

Mike




^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: Trouble w/sockets
  2013-03-03  4:48 ` Mike Gran
@ 2013-03-03  5:36   ` mark
  2013-03-03  6:35     ` Mike Gran
  2013-03-03  7:29     ` Thien-Thi Nguyen
  2013-03-03 10:36   ` Chris Vine
  1 sibling, 2 replies; 10+ messages in thread
From: mark @ 2013-03-03  5:36 UTC (permalink / raw)
  To: Mike Gran; +Cc: guile-user

Mike Gran <spk121@yahoo.com> writes:

>
> Crash? Or throw an error?  I definitely shouldn't crash, but, I could see
> how it could throw an error on Guile 2.0.

Sadly, it does crash. No error message at all, so it's probably a
segfault or something of that kind.

> The problem with `write-char' in Guile 2.0 is that it does all the
> conversion to the current locale.  So, once you start hitting the bytes
> greater than 127 in your string, `write-char' tries to convert each
> byte to something in your encoding.
>
> If your encoding is "C" or anything that strictly uses ASCII as its
> character encoding, it'll throw an error when its trying to print any
> byte above 127.  If your encoding is UTF-8, those high bytes will become
> two byte strings.
>
> Ideally you'd be able to use bytevectors or binary ports or some such.

Binary ports are nice to work with; the trouble I have is that in the
end it's still my job to write the "read" and "write!" functions that
interface with the underlying port, and there's no guarantee that I'll
do that right. Still, it confines a lot of potential problems to one or
two places.

> But you can also fake it by setting the port encoding to ISO-8859-1.
> In that encoding the characters 0 to 255 map one-to-one with the bytes
> from 0 to 255.
> (set-port-encoding! sock "ISO-8859-1")

That's a good point! Unfortunately the code I provided before still
crashes even if I add that line before doing any reading from the port.

I tried adding buffering to the port, and now when I attempt to read
from it after writing the message and flushing it, I get an error that
the "resource is temporarily unavailable." Perhaps there's something I
need to do before connecting to the X server to ensure that it doesn't
hang up on me. Time to go look at the xcb C source code again...

> Hope this helps,

Thanks, I think it will, despite my apparent frustration. These encoding
issues were likely to crop up later even if they aren't the cause of my
current troubles.

-- 
Mark Witmer



^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: Trouble w/sockets
  2013-03-03  5:36   ` mark
@ 2013-03-03  6:35     ` Mike Gran
  2013-03-03  7:29     ` Thien-Thi Nguyen
  1 sibling, 0 replies; 10+ messages in thread
From: Mike Gran @ 2013-03-03  6:35 UTC (permalink / raw)
  To: mark@markwitmer.com; +Cc: guile-user@gnu.org

>> Crash? Or throw an error?  I definitely shouldn't crash, but, I could see
>> how it could throw an error on Guile 2.0.
>
>Sadly, it does crash. No error message at all, so it's probably a
>segfault or something of that kind.

Dunno, then.  (At the risk of telling you something that you already know)
you could always run it from within a debugger to catch the location
of the segfault.  Or you could run it within `strace', if your operating
systems offer that.
 
Good luck,
 
Mike



^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: Trouble w/sockets
  2013-03-03  5:36   ` mark
  2013-03-03  6:35     ` Mike Gran
@ 2013-03-03  7:29     ` Thien-Thi Nguyen
  2013-03-04  4:18       ` mark.d.witmer
  1 sibling, 1 reply; 10+ messages in thread
From: Thien-Thi Nguyen @ 2013-03-03  7:29 UTC (permalink / raw)
  To: mark; +Cc: guile-user

[-- Attachment #1: Type: text/plain, Size: 569 bytes --]

() mark@markwitmer.com
() Sun, 03 Mar 2013 00:36:09 -0500

   an error that the "resource is temporarily unavailable."  Perhaps
   there's something I need to do before connecting to the X server to
   ensure that it doesn't hang up on me.

Check out Xnest -- useful for sniffing protocol.

I suspect a little patience is all your code needs.  E.g., see ttn-do
module ‘(ttn-do zzz x-protocol)’ proc ‘-connect’, subproc ‘get-setup’,
wherein there is a ‘select’ + ‘usleep’ loop.

[cc trimmed]

-- 
Thien-Thi Nguyen
GPG key: 4C807502

[-- Attachment #2: Type: application/pgp-signature, Size: 197 bytes --]

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: Trouble w/sockets
  2013-03-03  4:48 ` Mike Gran
  2013-03-03  5:36   ` mark
@ 2013-03-03 10:36   ` Chris Vine
  2013-03-04 13:29     ` Ludovic Courtès
  1 sibling, 1 reply; 10+ messages in thread
From: Chris Vine @ 2013-03-03 10:36 UTC (permalink / raw)
  To: Mike Gran; +Cc: mark@markwitmer.com, guile-user@gnu.org

On Sat, 2 Mar 2013 20:48:45 -0800 (PST)
Mike Gran <spk121@yahoo.com> wrote:
[snip]
> The problem with `write-char' in Guile 2.0 is that it does all the
> conversion to the current locale.  So, once you start hitting the
> bytes greater than 127 in your string, `write-char' tries to convert
> each byte to something in your encoding.
> 
> If your encoding is "C" or anything that strictly uses ASCII as its
> character encoding, it'll throw an error when its trying to print any
> byte above 127.  If your encoding is UTF-8, those high bytes will
> become two byte strings.
> 
> Ideally you'd be able to use bytevectors or binary ports or some such.
> 
> But you can also fake it by setting the port encoding to ISO-8859-1.
> In that encoding the characters 0 to 255 map one-to-one with the bytes
> from 0 to 255.
> (set-port-encoding! sock "ISO-8859-1")

Whilst this seems to be a side issue with respect to the OP's
problem, with R6RS you can use the 'put-u8' procedure to write
individual octets to a binary port (and 'get-u8' to read them) [1].

I know guile-2.0 doesn't distinguish between text and binary ports, but
presumably these procedures work without causing the port to undertake
charset conversion otherwise they are useless.  For example, I notice
that a port created with the 'pipe' procedure reports itself as both a
binary port and a textual port if 'setlocale' has not been called, but
as a textual port only if (setlocale LC_ALL "") has been called.
However, this does not seem to mean anything: in either case put-u8 and
get-u8 appear to work correctly.

Chris

[1] A someone unfortunate choice of name.  Here u8 presumably means
unsigned octet, not UTF-8 as in C11 and C++11.



^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: Trouble w/sockets
  2013-03-03  7:29     ` Thien-Thi Nguyen
@ 2013-03-04  4:18       ` mark.d.witmer
  2013-03-04  4:38         ` mark.d.witmer
  2013-03-04 10:02         ` Thien-Thi Nguyen
  0 siblings, 2 replies; 10+ messages in thread
From: mark.d.witmer @ 2013-03-04  4:18 UTC (permalink / raw)
  To: Thien-Thi Nguyen; +Cc: guile-user

Thien-Thi Nguyen <ttn@gnuvola.org> writes:

> () mark@markwitmer.com
> () Sun, 03 Mar 2013 00:36:09 -0500
>
>    an error that the "resource is temporarily unavailable."  Perhaps
>    there's something I need to do before connecting to the X server to
>    ensure that it doesn't hang up on me.
>
> Check out Xnest -- useful for sniffing protocol.

Cool; I'll check it out.

>
> I suspect a little patience is all your code needs.  E.g., see ttn-do
> module ‘(ttn-do zzz x-protocol)’ proc ‘-connect’, subproc ‘get-setup’,
> wherein there is a ‘select’ + ‘usleep’ loop.

Ok, that code helps a lot. I see that you use wrapped calls writev() and
readv() to communicate with the socket. Using writev() gets rid of the
broken pipe error and I successfully write my connection initiation
request to the X server. But calls to readv() after I do the select +
usleep loop you suggest here just give me garbage data. (read-char) gets
#<eof>.

> [cc trimmed]

Thanks to everyone for their help. I feel like I'm close to figuing this
out, but I probably need to take a break from this for a
while. Hopefully I'll get this working at some point in the relatively
near future!

-- 
Mark Witmer



^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: Trouble w/sockets
  2013-03-04  4:18       ` mark.d.witmer
@ 2013-03-04  4:38         ` mark.d.witmer
  2013-03-04 10:02         ` Thien-Thi Nguyen
  1 sibling, 0 replies; 10+ messages in thread
From: mark.d.witmer @ 2013-03-04  4:38 UTC (permalink / raw)
  To: guile-user

mark.d.witmer@gmail.com writes:

> But calls to readv() after I do the select + usleep loop you suggest
> here just give me garbage data. (read-char) gets #<eof>.
>

Oh, and the return value (bytes read) from readv() is zero, so the
garbage data is just stuff in an unitialized bytevector. Looks like the
socket is still getting closed early.

>
> Thanks to everyone for their help. I feel like I'm close to figuing this
> out, but I probably need to take a break from this for a
> while. Hopefully I'll get this working at some point in the relatively
> near future!

Ok, now I'm taking a (multi-day, hopefully) break... thanks all.

-- 
Mark Witmer



^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: Trouble w/sockets
  2013-03-04  4:18       ` mark.d.witmer
  2013-03-04  4:38         ` mark.d.witmer
@ 2013-03-04 10:02         ` Thien-Thi Nguyen
  1 sibling, 0 replies; 10+ messages in thread
From: Thien-Thi Nguyen @ 2013-03-04 10:02 UTC (permalink / raw)
  To: mark.d.witmer; +Cc: guile-user

[-- Attachment #1: Type: text/plain, Size: 878 bytes --]

() mark.d.witmer@gmail.com
() Sun, 03 Mar 2013 23:18:32 -0500

   Using writev() gets rid of the broken pipe error and I successfully
   write my connection initiation request to the X server.

If you can prove this, then perhaps you have found a bug in the server.

   but I probably need to take a break from this for a while

Another idea is to restart X.  I remember that helped sometimes.  In
theory, failed connection attempts should not leave persistent changes
in the server state (modulo incremented counters), but it's also true
that the vast majority of client interactions are via Xlib (et al), so
there might be some shared quirks (both server and Xlib are wrong
somehow but that's OK because they are "compatibly wrong") in play.

Anyway, the point is: killing X is a good excuse to take a break.  :-D

-- 
Thien-Thi Nguyen
GPG key: 4C807502

[-- Attachment #2: Type: application/pgp-signature, Size: 197 bytes --]

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: Trouble w/sockets
  2013-03-03 10:36   ` Chris Vine
@ 2013-03-04 13:29     ` Ludovic Courtès
  0 siblings, 0 replies; 10+ messages in thread
From: Ludovic Courtès @ 2013-03-04 13:29 UTC (permalink / raw)
  To: guile-user

Chris Vine <chris@cvine.freeserve.co.uk> skribis:

> Whilst this seems to be a side issue with respect to the OP's
> problem, with R6RS you can use the 'put-u8' procedure to write
> individual octets to a binary port (and 'get-u8' to read them) [1].

I concur, binary I/O primitives are what should be used for binary
protocols like this (info "(guile) R6RS I/O Ports").

Ludo’.




^ permalink raw reply	[flat|nested] 10+ messages in thread

end of thread, other threads:[~2013-03-04 13:29 UTC | newest]

Thread overview: 10+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2013-03-03  3:38 Trouble w/sockets mark
2013-03-03  4:48 ` Mike Gran
2013-03-03  5:36   ` mark
2013-03-03  6:35     ` Mike Gran
2013-03-03  7:29     ` Thien-Thi Nguyen
2013-03-04  4:18       ` mark.d.witmer
2013-03-04  4:38         ` mark.d.witmer
2013-03-04 10:02         ` Thien-Thi Nguyen
2013-03-03 10:36   ` Chris Vine
2013-03-04 13:29     ` Ludovic Courtès

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).