Building IP and Port from Byte Buffer - lisp

I have a byte buffer 6 bytes long first four contains ip address last 2 contains port, in big endian notation.
to get the ip i am using,
(apply str (interleave (map int (take 4 peer)) (repeat ".")))
Is casting bytes to int safe to get the ip address?
and also in java i use,
int port = 0;
port |= peerList[i+4] & 0xFF;
port <<= 8;
port |= peerList[i+5] & 0xFF;
this snippet to get the port address. How can i convert this to clojure?

yes mapping them to should be safe in this case because any leading zeros that are intoduced by writing into a larger data type will drop away again when it is converted into a string
The second part gets a lot easier because you are starting with a list of bytes.
(+ (* 256 (nth 5 peer)) (nth 4 peer))
A more general function for turning lists of bytes into numbers pulled from here
(defn bytes-to-num [bytes]
(let [powers (iterate #(* % 256) 1)]
(reduce + 0 (map * bytes powers))))

Related

(DrRacket) String manipulation problem creating student emails

I am having trouble with finding the part of the string for the 1st name when the goose email length is less then 9
(check-expect( goose-mail "becky""anderson"12)"12abecky#uragoose.ca")
At Goose University, students are given a unique username based on their name and a special ID
number. The username starts with the special ID number, followed by the first letter of their last
name, and then followed by their first name. All of the usernames are restricted to a maximum of
9 letters, therefore it is often the case that only a portion of the first name is included. All of the
usernames are in lower case. The special ID number is a positive integer that is less than 1000. The
email address is the username with “#uragoose.ca" appended to it.
Write a Racket function goose-mail that consumes two non-empty strings first-name, last-name,
and a non-negative integer ID-num, where 0 ≤ ID-num ≤ 999 and produces the email address for the
student with the specified first and last names and ID number. The first name and last name are
provided in lower case.
>
What I have so far is
(check-expect(1st-last-name-letter "pham")"p")
(define(1st-last-name-letter L)
(substring L 0 1))
(check-expect(ID-num 12)"12")
(define (ID-num ID)
(number->string ID))
(check-expect(user-name "andrew" "pham" 123)"123pandrew")
(define(user-name first-name last-name ID)
(string-append (string-append(ID-num ID)(1st-last-name-letter last-name))
first-name) )
We just need to check the length of the resulting username, and trim it to the required size if necessary:
(define (user-name first-name last-name ID)
(let ((username (string-append (ID-num ID) (1st-last-name-letter last-name) first-name)))
(if (<= (string-length username) 9)
username
(substring username 0 9))))

perl bitwise AND and bitwise shifting

I was reading some example code snippet for the module Net::Pcap::Easy, and I came across this piece of code
my $l3protlen = ord substr $raw_bytes, 14, 1;
my $l3prot = $l3protlen & 0xf0 >> 2; # the protocol part
return unless $l3prot == 4; # return unless IPv4
my $l4prot = ord substr $packet, 23, 1;
return unless $l4prot == '7';
After doing a total hex dump of the raw packet $raw_bytes, I can see that this is an ethernet frame, and not on a TCP/UDP packet. Can someone please explain what the above code does?
For parsing the frame, I looked up this page.
Now onto the Perl...
my $l3protlen = ord substr $raw_bytes, 14, 1;
Extract the 15th byte (character) from $raw_bytes, and convert to its ordinal value (e.g. a character 'A' would be converted to an integer 65 (0x41), assuming the character set is ASCII). This is how Perl can handle binary data as if it were a string (e.g. passing it to substr) but then let you get the binary values back out and handle them as numbers. (But remember TMTOWTDI.)
In the IPv4 frame, the first 14 bytes are the MAC header (6 bytes each for destination and source MAC address, followed by 2-byte Ethertype which was probably 0x8000 - you could have checked this). Following this, the 15th byte is the start of the Ethernet data payload: the first byte of this contains Version (upper 4 bytes) and Header Length in DWORDs (lower 4 bytes).
Now it looks to me like there is a bug in the next line of this sample code, but it may well normally work by a fluke!
my $l3prot = $l3protlen & 0xf0 >> 2; # the protocol part
In Perl, >> has higher precedence than &, so this will be equivalent to
my $l3prot = $l3protlen & (0xf0 >> 2);
or if you prefer
my $l3prot = $l3protlen & 0x3c;
So this extracts bits 2 - 5 from the $l3prot value: the mask value 0x3c is 0011 1100 in binary. So for example a value of 0x86 (in binary, 1000 0110) would become 0x04 (binary 0000 0100).
In fact a 'normal' IPv4 value is 0x45, i.e. protocol type 4, header length 5 dwords. Mask that with 0x3c and you get... 4! But only by fluke: you have tested the top 2 bits of the length, not the protocol type!
This line should surely be
my $l3prot = ($l3protlen & 0xf0) >> 4;
(note brackets for precedence and a shift of 4 bits, not 2). (I found this same mistake in the CPAN documentation so I guess it's probably quite widely spread.)
return unless $l3prot == 4; # return unless IPv4
For IPv4 we expect this value to be 4 - if it isn't, jump out of the function right away. (So the wrong code above gives the result which lets this be interpreted as an IPv4 packet, but only by luck.)
my $l4prot = ord substr $packet, 23, 1;
Now extract the 24th byte and convert to ordinal value in the same way. This is the Protocol byte from the IP header:
return unless $l4prot == '7';
We expect this to be 7 - if it isn't jump out of the function right away. (According to IANA, 7 is "Core-based trees"... but I guess you know which protocols you are interested in!)

Emacs byte-to-position function is not consistent with document?

Emacs 24.3.1, Windows 2003
I found the 'byte-to-position' function is a little strange.
According to the document:
-- Function: byte-to-position byte-position
Return the buffer position, in character units, corresponding to
given BYTE-POSITION in the current buffer. If BYTE-POSITION is
out of range, the value is `nil'. **In a multibyte buffer, an
arbitrary value of BYTE-POSITION can be not at character boundary,
but inside a multibyte sequence representing a single character;
in this case, this function returns the buffer position of the
character whose multibyte sequence includes BYTE-POSITION.** In
other words, the value does not change for all byte positions that
belong to the same character.
We can make a simple experiment:
Create a buffer, eval this expression: (insert "a" (- (max-char) 128) "b")
Since the max bytes number in Emacs' internal coding system is 5, the character between 'a' and 'b' is 5 bytes. (Note that the last 128 characters is used for 8 bits raw bytes, their size is only 2 bytes.)
Then define and eval this test function:
(defun test ()
(interactive)
(let ((max-bytes (1- (position-bytes (point-max)))))
(message "%s"
(loop for i from 1 to max-bytes collect (byte-to-position i)))))
What I get is "(1 2 3 2 2 2 3)".
The number in the list represents the character position in the buffer. Because there is a 5 bytes big character, there should be five '2' between '1' and '3', but how to explain the magic '3' in the '2's ?
This was a bug. I no longer see this behavior in 26.x. You can read more about it here (which actually references this SO question).
https://debbugs.gnu.org/cgi/bugreport.cgi?bug=20783

How can I work with a single byte and binary! byte arrays in Rebol 3?

In Rebol 2, it is possible to use to char! to produce what is effectively a single byte, that you can use in operations on binaries such as append:
>> buffer: #{DECAFBAD}
>> data: #{FFAE}
>> append buffer (to char! (first data))
== #{DECAFBADFF}
Seems sensible. But in Rebol 3, you get something different:
>> append buffer (to char! (first data))
== #{DECAFBADC3BF}
That's because it doesn't model single characters as single bytes (due to Unicode). So the integer value of first data (255) is translated into a two-byte sequence:
>> to char! 255
== #"ÿ"
>> to binary! (to char! 255)
== #{C3BF}
Given that CHAR! is no longer equivalent to a byte in Rebol 3, and no BYTE! datatype was added (such that a BINARY! could be considered a series of these BYTE!s just as a STRING! is a series of CHAR!), what is one to do about this kind of situation?
Use an integer!, the closest match we have for expressing a byte in R3, at the moment.
Note that integers are range-checked when used as bytes in context of a binary!:
>> append #{} 1024
** Script error: value out of range: 1024
** Where: append
** Near: append #{} 1024
For your first example, you actually append one element of one series to another series of the same type. In R3 you can express this in the obvious and most straight-forward way:
>> append #{DECAFBAD} first #{FFAE}
== #{DECAFBADFF}
So for that matter, a binary! is a series of range-constrained integer!s.
Unfortunately, that won't work in R2, because its binary! model was just broken in many tiny ways, including the above. While conceptually a binary! in R2 can be considered a series of char!s, that concept is not consistently implemented.
>> buffer: #{DECAFBAD}
== #{DECAFBAD}
>> data: #{FFAE}
== #{FFAE}
>> append buffer data/1
== #{DECAFBADFF}
The easiest workaround for the issue in both Rebol 2 and Rebol 3 is to use COPY/PART. This way, rather than trying to reduce your content to a byte value, you keep it as a binary series type. You're merely appending a binary sequence of length 1:
>> append buffer (copy/part data 1)
== #{DECAFBADFF}
It does seem that for completeness, Rebol 3 would have a BYTE! type, as calling it a "series of INTEGER!" clearly does not match the precedent set by STRING!
It's open source, so you (um, I?) might try adding it and seeing what the full ramifications are. :-)

Convert string to code in Scheme

How do I convert a string into the corresponding code in PLT Scheme (which does not contain the string->input-port method)? For example, I want to convert this string:
"(1 (0) 1 (0) 0)"
into this list:
'(1 (0) 1 (0) 0)
Is it possible to do this without opening a file?
Scheme has procedure read for reading s-expressions from input port and you can convert a string to input stream with string->input-port. So, you can read a Scheme object from a string with
(read (string->input-port "(1 (0) 1 (0) 0)"))
I don't have Scheme installed, so I only read it from reference and didn't actually test it.
From PLT Scheme manual:
(open-input-string string [name-v]) creates an input port that reads bytes from the UTF-8 encoding (see section 1.2.3) of string. The optional name-v argument is used as the name for the returned port; the default is 'string.
From this similar question on comp.lang.scheme you can save the string to a file then read from it.
That might go something like this example code:
(let ((my-port (open-output-file "Foo")))
(display "(1 (0) 1 (0) 0)" my-port)
(close-output-port my-port))
(let* ((my-port (open-input-file "Foo"))
(answer (read my-port)))
(close-input-port my-port)
answer)
Many schemes have with-input-from-string str thunk that executes thunk in a context where str is the standard input port. For example in gambit scheme:
(with-input-from-string "(foo bar)"
(lambda () (read)))
evaluates to:
(foo bar)
The lambda is necessary because a thunk should be a procedure taking no arguments.