Robert Newson wrote: > Hi, > > I'm developing an IMAP server in Java > (http://wallace.sourceforge.net). I'm currently building the I/O layer > before moving on to the higher level commands. > Cool, how'd you come up with the name (just curious =P)? I'm working on building a SMTP server that is utilizes the networking libraries that are being developed here. Later I plan on adding POP3 and IMAP4 servers, also utilizing the networking libraries here as well as the AAA framework (formerly known as Janus) that Vincent is working developing. I've been in kind of a holding pattern lately tho, what with the holidays and all. I've also been waiting for the protocol api to develop a little further and standardize a little more before developing too much more, that way either MINA or (my preference) sedang can be used for networking. We should talk more about this stuff. > I've been communicating with Trustin as I'm currently using the MINA > framework (having migrated from Netty very recently). > > IMAP has an interesting I/O model where most strings (and all mail > messages) can be transferred as 'literals'. Here's an example of a > conversation; > > Client: 001 LOGIN {8}\r\n > Server: + continue for 8 bytes.\r\n > Client: username\r\n{8}\r\n > Server: + continue for 8 bytes.\r\n > Client: password\r\n > > Essentially, the client has to wait for a continuation message before > it can send the rest of the data (this is most useful for large > numbers of bytes, of course, but can occur for any number of bytes, > including zero). > > I started building an IMAP grammar with Antlr which can handle a > useful subset of the full IMAP grammar and I'm happy with this > approach. The generated parser blocks for I/O if its input is > incomplete, so I need to decode in several passes. > > My question (finally) is, is the StatefulDecoder work you're doing in > the Asn1 project applicable to my problem? I see that there's a basic > level that is Asn1-agnostic. > > I'm keen to build a high-performance, non-blocking and elegant > solution to this problem, but I'm now thrashing backwards and forwards > for the right tool. > In some of my initial work on the SMTP server I've been using the StatefulDecoder. Since the grammar for SMTP is pretty simple I just plan on writing a parser by hand to process the strings and generate the Command objects to be passed to the next stage. I haven't looked into the IMAP spec yet, but is it really complicated and large enough that you need to use a parser generator like Antlr? Here's what I'm doing right now (you can take a look at http://dropbox.compunetconsulting.com). Basically, my SMTPDecoder the decode() method uses two buffers, a StringBuffer for the current command and byte[] for grabbing data from the ByteBuffer parameter provided to the decode() method. As much data as is possible from the network is taken from the ByteBuffer in one get() method and put into the temporary byte[]. (This is the part I don't like but can't figure out a way around ATM) I then have to iterate over the data in the temporary byte[] looking for a to indicate the end of the command. If I don't get them I append to the command StringBuffer. Once I do get them I pass the contents of the command StringBuffer and pass them to the command parser which returns a Command object that is passed to the next stage with the decodeOccurred() callback. I then continue processing data in the ByteBuffer if there is any (in case a client tries to send multiple commands all at once). I think this will work well, the only part I don't like is having to iterate over the data looking for a . I just seems too inefficient, because then I'm basically doing two passes over the data the client sends me (once here and then again in the command parser). But, I can't always trust the only a single command will be in the ByteBuffer, so I don't really have a choice. I think something similar will work for you're case. If you (or anyone else) can offer a better solution, I'm more than open to it (I'd be in your debt ;). Rich