Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP

Loading…

Updated 9p draft #4

Merged
merged 32 commits into from

2 participants

@wolneykien

Uses "mempair" module to parse the messages. Support multiple connections and sessions with separate message queues.

Please, pull the other branches accordingly:

  • mempair — the "mempair" module;
  • templates — the messages.py template with the code generator (is necessary to update and/or refactor the definitions of the 9P message classes);
  • master — the original "master" branch with "9p" and "mempair" merged into;
  • testing — the original "testing" branch with "9p" and "mempair merged into.
Paul Wolneykien added some commits
Paul Wolneykien Add a source file for the message classes (draft) e7673d2
Paul Wolneykien Define the message type classes
Update the source file from its template in the `templates' branch.
5ef3c5e
Paul Wolneykien Replace the inline docstring with a comment 82095c9
Paul Wolneykien Export the maximal message size constant a1dbd0d
Paul Wolneykien Revert "Define the message type classes"
This reverts commit 5ef3c5e.
27d0072
Paul Wolneykien Redefine base classes to be used with the mempair module 22dd4a2
Paul Wolneykien Define message classes
Add the generated definition of the message classes.
See the `templates' branch for more information.
b9a32f9
Paul Wolneykien Define the `p9qid' structure 1a9a6d6
Paul Wolneykien Initialize the __all__ variable 5ad9abc
Paul Wolneykien Use byte array types for `data' fields
Use byte array types for `data' fields of the Rread and Twrite
messages.
865213f
Paul Wolneykien Add the normal (default) message size constant
Let the default message buffer length be the usual memory page length
of 4096 bytes.
55aebef
Paul Wolneykien Fix definition of some tails
- Do not define a tail if header is empty.
- Use index for variable-length complex arrays.
1d630f5
Paul Wolneykien Export all p9* types d21272b
Paul Wolneykien Use mempair to parse incoming message header 14d98b7
Paul Wolneykien Add a warning about the genarated part cb9d870
Paul Wolneykien Export the message types explicitly 0b23362
Paul Wolneykien Use a queue to process messages asynchronously d7eae24
Paul Wolneykien Get T-version/R-version to work a7b7d06
Paul Wolneykien Implement multi-message sessions 51aec5d
Paul Wolneykien Fix the reply message send
Use the client socket.
798c354
Paul Wolneykien Fix the send buffer length
Use buf/databuf mempair methods.
e6b22cc
Paul Wolneykien Fix the `size' field of the message to be sent b6d990c
Paul Wolneykien Define arrays and strings only as tails c98991c
Paul Wolneykien Fix/improve the cdarclass descriptions c7494bf
Paul Wolneykien Fix the Rerror message composing 0eeda72
Paul Wolneykien Fix the `size' field before length check is done on reply caa4ee9
Paul Wolneykien Address the header fields by name to test the new mempair functionality a70c7ba
Paul Wolneykien Name variable-length fields via `cdrmap' ee425f9
Paul Wolneykien Address all fields by name 07c9fb2
Paul Wolneykien Export the "p9msgclasses" tuple 1ca838b
Paul Wolneykien Use class constants for message type numbers 44875e9
Paul Wolneykien Define the _type field with a type number value for each message class 21b44e3
@svinota svinota merged commit a42eb3a into svinota:9p
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Commits on Aug 9, 2011
  1. Add a source file for the message classes (draft)

    Paul Wolneykien authored
Commits on Aug 10, 2011
  1. Define the message type classes

    Paul Wolneykien authored
    Update the source file from its template in the `templates' branch.
  2. Replace the inline docstring with a comment

    Paul Wolneykien authored
  3. Export the maximal message size constant

    Paul Wolneykien authored
Commits on Aug 29, 2011
  1. Revert "Define the message type classes"

    Paul Wolneykien authored
    This reverts commit 5ef3c5e.
  2. Redefine base classes to be used with the mempair module

    Paul Wolneykien authored
Commits on Sep 22, 2011
  1. Define message classes

    Paul Wolneykien authored
    Add the generated definition of the message classes.
    See the `templates' branch for more information.
  2. Define the `p9qid' structure

    Paul Wolneykien authored
Commits on Oct 5, 2011
  1. Initialize the __all__ variable

    Paul Wolneykien authored
  2. Use byte array types for `data' fields

    Paul Wolneykien authored
    Use byte array types for `data' fields of the Rread and Twrite
    messages.
Commits on Oct 6, 2011
  1. Add the normal (default) message size constant

    Paul Wolneykien authored
    Let the default message buffer length be the usual memory page length
    of 4096 bytes.
  2. Fix definition of some tails

    Paul Wolneykien authored
    - Do not define a tail if header is empty.
    - Use index for variable-length complex arrays.
  3. Export all p9* types

    Paul Wolneykien authored
  4. Use mempair to parse incoming message header

    Paul Wolneykien authored
  5. Add a warning about the genarated part

    Paul Wolneykien authored
  6. Export the message types explicitly

    Paul Wolneykien authored
Commits on Nov 28, 2011
  1. Use a queue to process messages asynchronously

    Paul Wolneykien authored
Commits on Nov 29, 2011
  1. Get T-version/R-version to work

    Paul Wolneykien authored
  2. Implement multi-message sessions

    Paul Wolneykien authored
  3. Fix the reply message send

    Paul Wolneykien authored
    Use the client socket.
  4. Fix the send buffer length

    Paul Wolneykien authored
    Use buf/databuf mempair methods.
  5. Fix the `size' field of the message to be sent

    Paul Wolneykien authored
  6. Define arrays and strings only as tails

    Paul Wolneykien authored
  7. Fix/improve the cdarclass descriptions

    Paul Wolneykien authored
  8. Fix the Rerror message composing

    Paul Wolneykien authored
  9. Fix the `size' field before length check is done on reply

    Paul Wolneykien authored
Commits on Jan 11, 2012
Commits on Jan 12, 2012
  1. Name variable-length fields via `cdrmap'

    Paul Wolneykien authored
  2. Address all fields by name

    Paul Wolneykien authored
  3. Export the "p9msgclasses" tuple

    Paul Wolneykien authored
  4. Use class constants for message type numbers

    Paul Wolneykien authored
This page is out of date. Refresh to see the latest.
Showing with 830 additions and 31 deletions.
  1. +285 −31 lib/cxnet/cxnet/cx9p/core.py
  2. +545 −0 lib/cxnet/cxnet/cx9p/messages.py
View
316 lib/cxnet/cxnet/cx9p/core.py
@@ -26,7 +26,7 @@
# ctypes structures
from ctypes import Structure, Union
# ctypes functions
-from ctypes import byref, sizeof, create_string_buffer
+from ctypes import byref, sizeof, create_string_buffer, resize
# ctypes simple types
from ctypes import c_short, c_ushort, c_byte, c_ulong, c_uint32, c_uint16, c_ubyte, c_uint64, c_uint8
@@ -34,7 +34,96 @@
from cxnet.common import libc
from socket import htons, htonl, ntohs, AF_INET, SOCK_STREAM, SOL_SOCKET, SO_REUSEADDR
-MAX_MSG_SIZE = 8192
+from messages import *
+from mempair import *
+
+# Modules for asynchronous queue processing
+import threading
+import Queue
+
+# Limit the size of the message queue
+MAXWAITING = 1024
+
+# The number of threads per queue
+QTHREADS = 2
+
+def basereply (tmsg, rtype = -1):
+ """
+ Returns the corresponding R-message mempair object for
+ a given T-message mempair object
+ """
+ if rtype < 0:
+ rtype = tmsg.type + 1
+ msgdata = (c_ubyte * NORM_MSG_SIZE)()
+ replymsg = mempair(p9msg, msgdata)
+ replymsg.type = rtype
+ replymsg.tag = tmsg.tag
+ (baddr, bsize) = replymsg.carbuf()
+ replymsg.size = bsize
+
+ return replymsg
+
+def errorreply (tmsg, emsg):
+ """
+ Returns the Rerror message mempair object with a given
+ error message for a given T-message
+ """
+ replymsg = basereply(tmsg, Rerror._type)
+ replymsg.ename.len = len(emsg)
+ replymsg.ename.raw = emsg
+ return replymsg
+
+
+class p9socketworker(threading.Thread):
+ """
+ Processes the T-message queue running a thread
+ """
+ def __init__ (self, sock):
+ self.__sock = sock
+ threading.Thread.__init__(self)
+
+ def getversion (self, verstr, msize):
+ """
+ Returns a tuple (sverstr, smsize), where ``sverstr`` is the
+ 9P version that is supported by this server equal or less than
+ the version given in ``verstr`` parameter and ``smsize`` is the
+ maximum message length that this server is ready to receive or
+ send equal or less than the size given in ``msize``
+ """
+
+ if msize <= MAX_MSG_SIZE:
+ rmsize = msize
+ else:
+ rmsize = MAX_MSG_SIZE
+ return (VERSION9P, rmsize)
+
+ def run (self):
+ while True:
+ (session, msg) = self.__sock.nextmsg()
+ if msg is None:
+ self.__sock.debug ("Worker finished")
+ break # reached the end of the queue
+
+ if self.__sock.closed:
+ self.__sock.reply (errorreply (msg, "The server is closed"))
+
+ if msg.type == Tversion._type:
+ session.debug ("Requested 9P version: %s, maximum size: %i bytes" % (msg.version.raw, msg.msize))
+ (rver, rmsize) = self.getversion(msg.version.raw, msg.msize)
+ session.msize = rmsize
+ rmsg = basereply(msg)
+ rmsg.msize = rmsize;
+ rmsg.version.len = len(rver)
+ rmsg.version.raw = rver
+ session.debug ("Supported 9P version: %s, maximum size: %i bytes" % (rmsg.version.raw, rmsg.msize))
+ else:
+ session.debug ("An unknown case! Message type: %i" % msg.type)
+ emsg = "Currently the message %s is not supported. Sorry!" % p9msgclasses[msg.type].__name__
+ rmsg = errorreply(msg, emsg)
+ session.debug (emsg)
+
+ session.reply(rmsg)
+
__all__ = [ "p9socket" ]
@@ -47,29 +136,19 @@ class sockaddr_in (Structure):
("sin_zero", (c_uint8 * 8)),
]
-class p9msg (Structure):
- """
- http://man.cat-v.org/plan_9/5/intro
- http://swtch.com/plan9port/man/man3/fcall.html
- """
- _fields_ = [
- ("size", c_uint32),
- ("type", c_ubyte),
- ("tag", c_uint16),
- ("data", (c_ubyte * MAX_MSG_SIZE)),
- ]
-
- def __str__(self):
- ret = hline(self,self.size)
- ret += "size: %s, type: %s, tag: %s\n" % (self.size, self.type, self.tag)
- return ret
-
class p9socket (object):
"""
9P core
"""
fd = None # socket file descriptor
+ # The message queue
+ __msgq = Queue.Queue(MAXWAITING)
+
+ __debug = True
+
+ closed = True
+
def __init__(self, address='0.0.0.0',port=10001):
"""
Create and bind socket structure
@@ -89,11 +168,19 @@ def __init__(self, address='0.0.0.0',port=10001):
self.close()
raise Exception("libc.bind(): errcode %i" % (l))
+ for i in range(QTHREADS):
+ p9socketworker(self).start()
+
def close(self):
"""
Close the socket
"""
+ for i in range(QTHREADS):
+ self.enqueue (None, None)
+ self.debug ("Waiting for queue workers to finish...")
+ self.__msgq.join()
libc.close(self.fd)
+ self.closed = True
def dial(self,target):
"""
@@ -101,31 +188,198 @@ def dial(self,target):
"""
pass
+ def enqueue (self, session, msg):
+ """
+ Enqueue the given reply message for later processing
+ """
+ self.__msgq.put((session, msg))
+
def serve(self):
"""
9p server
"""
libc.listen(self.fd,10)
+ self.closed = False
while True:
sa = sockaddr_in()
- s = libc.accept(self.fd, byref(sa), byref(c_uint32(sizeof(sa))))
- (l,msg) = self.recv(s)
- print("got message of",l,"bytes")
- print(msg)
- libc.close(s)
+ try:
+ s = libc.accept(self.fd, byref(sa), byref(c_uint32(sizeof(sa))))
+ p9session(self, s).start()
+ except:
+ self.close()
+ raise
+ def debug (self, dmsg):
+ """
+ Outputs the given debug message if in debug mode
+ """
+ if self.__debug:
+ print (dmsg)
- def recv(self,socket):
+ def nextmsg (self):
"""
+ Returns the next message from the queue
"""
- msg = p9msg()
- l = libc.recv(socket, byref(msg), sizeof(msg), 0)
+ msg = None
+ next = True
+ while next:
+ next = False
+ (session, msg) = self.__msgq.get()
+ if msg is None:
+ self.__msgq.task_done()
+ else:
+ next = (session.closed or session.clearflushed(msg))
+ return (session, msg)
+
+ def msgdone (self):
+ """
+ Tels the server that a message taken from the queue
+ is successfully processed
+ """
+ self.__msgq.task_done()
- return (l,msg)
- def send(self, msg, size=0):
+class p9session (threading.Thread):
+ """
+ Client-server connection via 9P
+ """
+ def __init__(self, p9sock, clsock, p9msize = MAX_MSG_SIZE):
"""
+ Initializes the session object bound to the specified
+ 9P socket instance
"""
- l = libc.send(self.fd, byref(msg), size, 0)
- return l
+ self.__sock = p9sock
+ self.__clsock = clsock
+ self.msize = p9msize
+ self.__lock = threading.Lock()
+ self.__flushed = {}
+ self.closed = False
+ threading.Thread.__init__(self)
+ def markflushed (self, oldtag):
+ """
+ Mark the given tag as flushed (aborted)
+ """
+ self.__lock.acquire()
+ self.__flushed[oldtag] = True
+ self.__lock.release()
+
+ def isflushed (self, msg):
+ """
+ Indicates if the given message is flushed (aborted)
+ """
+ return msg.tag in self.__flushed
+
+ def clearflushed (self, arg):
+ """
+ Unmark the given message or tag from the set of
+ flushed (aborted) messages/tags
+ """
+ if isinstance (arg, mempair):
+ tag = arg.tag
+ else:
+ tag = arg
+ self.__lock.acquire()
+ if tag in self.__flushed:
+ del self.__flushed[tag]
+ ret = True
+ else:
+ ret = False
+ self.__lock.release()
+ return ret
+
+ def run (self):
+ """
+ Receive and transmit messages
+ """
+ self.debug ("Start a new session")
+ try:
+ while not self.__sock.closed:
+ try:
+ (l, msg) = self.recv()
+ self.debug ("%i bytes received" % l)
+ except IOError:
+ break
+ if msg.type == Tflush._type:
+ self.markflushed (msg.oldtag)
+ self.debug ("Flush the %i tag" % msg.oldtag)
+ self.reply (basereply(msg), False)
+ else:
+ self.__sock.enqueue (self, msg)
+ libc.close(self.__clsock)
+ self.closed = True
+ self.debug ("The session is closed")
+ except:
+ libc.close(self.__clsock)
+ self.closed = True
+ self.debug ("The session is closed on an error")
+ raise
+
+ def nextmsg (self):
+ """
+ A proxy method to the parent socket ``nextmsg`` proc
+ """
+ return self.__sock.nextmsg()
+
+ def debug (self, dmsg):
+ """
+ A proxy method to the parent socket ``debug`` proc
+ """
+ self.__sock.debug("[session] " + dmsg)
+
+ def recv(self):
+ """
+ Receive a request message from the client
+ """
+ msgdata = (c_ubyte * NORM_MSG_SIZE)()
+ msg = mempair(p9msg, msgdata)
+ (baddr, blen) = msg.databuf()
+ l = libc.recv(self.__clsock, baddr, blen, 0)
+ hdr = msg.car()
+ if l > sizeof(hdr):
+ if hdr.size > l:
+ if hdr.size > MAX_MSG_SIZE:
+ raise IOError ("The message is too large: %d bytes" % hdr.size)
+ resize(msgdata, hdr.size)
+ (baddr, blen) = msg.databuf()
+ l2 = libc.recv(self.__clsock, baddr + hdr.size - l, blen - l, 0)
+ if l2 > 0:
+ l += l2
+ else:
+ raise IOError ("Unable to read the %d remaining bytes" % blen - l)
+ else:
+ raise IOError ("Unable to read the message")
+
+ return (l, msg)
+
+ def reply (self, rmsg, task_done = True):
+ """
+ Send the given reply message to the client.
+ The size of the message is checked not to exceed the
+ maximum message size, configured for this session.
+ According to the 9P spec, the maximum message size is
+ specified by the client with the T-version request.
+ If the message is longer than a message client is ready
+ to handle, then the Rerror message is sent and a
+ ValueError is raised
+ """
+ (baddr, blen) = rmsg.buf()
+ rmsg.size = blen
+ emsg = None
+ if rmsg.size > self.msize:
+ emsg = errorreply (rmsg, "The reply message is too long")
+ extra = emsg.size - self.msize
+ if extra > emsg.ename.len:
+ extra = emsg.ename.len
+ if extra > 0:
+ emsg.ename.len -= extra
+ emsg.size -= extra
+ (baddr, blen) = emsg.buf()
+ l = libc.send(self.__clsock, baddr, blen, 0)
+ self.debug ("%i bytes sent" % l)
+ if l < blen:
+ raise IOError ("Unable to send the message")
+ if task_done:
+ self.__sock.msgdone()
+ if emsg is not None:
+ raise ValueError ("The message is too long")
View
545 lib/cxnet/cxnet/cx9p/messages.py
@@ -0,0 +1,545 @@
+
+"""
+9P protocol messages
+
+http://man.cat-v.org/plan_9/5/intro
+http://swtch.com/plan9port/man/man3/fcall.html
+"""
+
+# Copyright (c) 2011 Peter V. Saveliev
+# Copyright (c) 2011 Paul Wolneykien
+#
+# This file is part of Connexion project.
+#
+# Connexion is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# Connexion is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with Connexion; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+
+
+# ctypes types and functions
+from ctypes import c_ubyte, c_char, c_uint16, c_uint32, c_uint64
+
+# 9P uses little-endian meta data
+from ctypes import LittleEndianStructure as Structure
+
+# The maximum message size is 8192 bytes
+MAX_MSG_SIZE = 8192
+__all__ = ["MAX_MSG_SIZE"]
+
+# Normal (default) message size: 4096 bytes -- one memory page.
+NORM_MSG_SIZE = 4096
+__all__ += ["NORM_MSG_SIZE"]
+
+class p9msg (Structure):
+ """
+ A 9P message head.
+ """
+ _pack_ = 1
+ _fields_ = [
+ ("size", c_uint32),
+ ("type", c_ubyte),
+ ("tag", c_uint16),
+ ]
+
+ def cdarclass (self):
+ """
+ Determines the message body class using the ``p9msgclasses``
+ tuple.
+ """
+ if self.type > 0 and self.type < len(p9msgclasses):
+ return p9msgclasses[self.type]
+ else:
+ raise ValueError("Unknown message type: %d" % (self.type))
+
+__all__ += ["p9msg"]
+
+class p9msgstring (Structure):
+ """
+ A 9P message string.
+ """
+ _pack_ = 1
+ _fields_ = [
+ ("len", c_uint16),
+ ]
+
+ def cdarclass (self):
+ """
+ Returns a character array type of the corresponding length.
+ """
+ return c_char * self.len
+
+__all__ += ["p9msgstring"]
+
+class p9msgarray (Structure):
+ """
+ A 9P message array.
+ """
+ _pack_ = 1
+ _fields_ = [
+ ("len", c_uint16),
+ ]
+
+ def cdarclass (self):
+ """
+ Returns a byte array type of the corresponding length.
+ """
+ return c_ubyte * self.len
+
+__all__ += ["p9msgarray"]
+
+class p9qid (Structure):
+ """
+ The 9P qid type.
+
+ The qid represents the server's unique identification for the file
+ being accessed: two files on the same server hierarchy are the same
+ if and only if their qids are the same.
+ """
+ _pack_ = 1
+ _fields_ = [
+ ("type", c_ubyte),
+ ("version", c_uint32),
+ ("path", c_uint64),
+ ]
+
+__all__ += ["p9qid"]
+
+
+# Do not edit the following.
+# The following code is generated automatically from the
+# 9P manual pages and C header files.
+# See the `templates' branch for details.
+
+
+# The 9P version implemented
+VERSION9P = "9P2000"
+
+
+class Tcreate (Structure):
+ """
+ 9P type 114 'create' request (transmit) message class
+ Open, create - prepare a fid for I/O on an existing or new file
+ """
+ _type = 114
+ _pack_ = 1
+ _fields_ = [
+ ("fid", c_uint32),
+ ]
+
+ class tail (Structure):
+ """
+ The static tail of the outer message class.
+ """
+ _pack_ = 1
+ _fields_ = [
+ ("perm", c_uint32),
+ ("mode", c_ubyte),
+ ]
+
+ def cdrmap (self):
+ """
+ Returns the map of the message tail:
+ * name ```p9msgstring```;
+ * _tail ```self.tail```.
+ """
+ return [("name", p9msgstring, 1), ("_tail", self.tail, 1)]
+
+class Rcreate (Structure):
+ """
+ 9P type 115 'create' reply (return) message class
+ Open, create - prepare a fid for I/O on an existing or new file
+ """
+ _type = 115
+ _pack_ = 1
+ _fields_ = [
+ ("qid", p9qid),
+ ("iounit", c_uint32),
+ ]
+
+
+class Tremove (Structure):
+ """
+ 9P type 122 'remove' request (transmit) message class
+ Remove - remove a file from a server
+ """
+ _type = 122
+ _pack_ = 1
+ _fields_ = [
+ ("fid", c_uint32),
+ ]
+
+class Rremove (Structure):
+ """
+ 9P type 123 'remove' reply (return) message class
+ Remove - remove a file from a server
+ """
+ _type = 123
+
+
+class Tversion (Structure):
+ """
+ 9P type 100 'version' request (transmit) message class
+ Version - negotiate protocol version
+ """
+ _type = 100
+ _pack_ = 1
+ _fields_ = [
+ ("msize", c_uint32),
+ ]
+
+ def cdrmap (self):
+ """
+ Returns the ``p9msgstring`` as the type of the message tail ``version``
+ """
+ return [("version", p9msgstring, 1)]
+
+class Rversion (Structure):
+ """
+ 9P type 101 'version' reply (return) message class
+ Version - negotiate protocol version
+ """
+ _type = 101
+ _pack_ = 1
+ _fields_ = [
+ ("msize", c_uint32),
+ ]
+
+ def cdrmap (self):
+ """
+ Returns the ``p9msgstring`` as the type of the message tail ``version``
+ """
+ return [("version", p9msgstring, 1)]
+
+
+class Tstat (Structure):
+ """
+ 9P type 124 'stat' request (transmit) message class
+ Stat, wstat - inquire or change file attributes
+ """
+ _type = 124
+ _pack_ = 1
+ _fields_ = [
+ ("fid", c_uint32),
+ ]
+
+class Rstat (Structure):
+ """
+ 9P type 125 'stat' reply (return) message class
+ Stat, wstat - inquire or change file attributes
+ """
+ _type = 125
+
+ def cdrmap (self):
+ """
+ Returns the ``p9msgarray`` as the type of the message tail ``stat``
+ """
+ return [("stat", p9msgarray, 1)]
+
+
+class Tclunk (Structure):
+ """
+ 9P type 120 'clunk' request (transmit) message class
+ Clunk - forget about a fid
+ """
+ _type = 120
+ _pack_ = 1
+ _fields_ = [
+ ("fid", c_uint32),
+ ]
+
+class Rclunk (Structure):
+ """
+ 9P type 121 'clunk' reply (return) message class
+ Clunk - forget about a fid
+ """
+ _type = 121
+
+
+class Tauth (Structure):
+ """
+ 9P type 102 'auth' request (transmit) message class
+ Attach, auth - messages to establish a connection
+ """
+ _type = 102
+ _pack_ = 1
+ _fields_ = [
+ ("afid", c_uint32),
+ ]
+
+ def cdrmap (self):
+ """
+ Returns the map of the message tail:
+ * uname ```p9msgstring```;
+ * aname ```p9msgstring```.
+ """
+ return [("uname", p9msgstring, 1), ("aname", p9msgstring, 1)]
+
+class Rauth (Structure):
+ """
+ 9P type 103 'auth' reply (return) message class
+ Attach, auth - messages to establish a connection
+ """
+ _type = 103
+ _pack_ = 1
+ _fields_ = [
+ ("aqid", p9qid),
+ ]
+
+
+class Topen (Structure):
+ """
+ 9P type 112 'open' request (transmit) message class
+ Open, create - prepare a fid for I/O on an existing or new file
+ """
+ _type = 112
+ _pack_ = 1
+ _fields_ = [
+ ("fid", c_uint32),
+ ("mode", c_ubyte),
+ ]
+
+class Ropen (Structure):
+ """
+ 9P type 113 'open' reply (return) message class
+ Open, create - prepare a fid for I/O on an existing or new file
+ """
+ _type = 113
+ _pack_ = 1
+ _fields_ = [
+ ("qid", p9qid),
+ ("iounit", c_uint32),
+ ]
+
+
+class Tflush (Structure):
+ """
+ 9P type 108 'flush' request (transmit) message class
+ Flush - abort a message
+ """
+ _type = 108
+ _pack_ = 1
+ _fields_ = [
+ ("oldtag", c_uint16),
+ ]
+
+class Rflush (Structure):
+ """
+ 9P type 109 'flush' reply (return) message class
+ Flush - abort a message
+ """
+ _type = 109
+
+
+class Tread (Structure):
+ """
+ 9P type 116 'read' request (transmit) message class
+ Read, write - transfer data from and to a file
+ """
+ _type = 116
+ _pack_ = 1
+ _fields_ = [
+ ("fid", c_uint32),
+ ("offset", c_uint64),
+ ("count", c_uint32),
+ ]
+
+class Rread (Structure):
+ """
+ 9P type 117 'read' reply (return) message class
+ Read, write - transfer data from and to a file
+ """
+ _type = 117
+ _pack_ = 1
+ _fields_ = [
+ ("count", c_uint32),
+ ]
+
+ def cdrmap (self):
+ """
+ Returns the ``(c_ubyte * count)`` as the type of the message tail ``data``
+ """
+ return [("data", (c_ubyte * count), 1)]
+
+
+class Terror (Structure):
+ """
+ 9P type 106 'error' request (transmit) message class
+ Error - return an error
+ Comment: illegal
+ """
+ _type = 106
+
+class Rerror (Structure):
+ """
+ 9P type 107 'error' reply (return) message class
+ Error - return an error
+ """
+ _type = 107
+
+ def cdrmap (self):
+ """
+ Returns the ``p9msgstring`` as the type of the message tail ``ename``
+ """
+ return [("ename", p9msgstring, 1)]
+
+
+class Twalk (Structure):
+ """
+ 9P type 110 'walk' request (transmit) message class
+ Walk - descend a directory hierarchy
+ """
+ _type = 110
+ _pack_ = 1
+ _fields_ = [
+ ("fid", c_uint32),
+ ("newfid", c_uint32),
+ ("nwname", c_uint16),
+ ]
+
+ def cdrmap (self):
+ """
+ Returns the map of the message tail:
+ * wname ```p9msgstring``` * nwname.
+ """
+ return [("wname", p9msgstring, nwname)]
+
+class Rwalk (Structure):
+ """
+ 9P type 111 'walk' reply (return) message class
+ Walk - descend a directory hierarchy
+ """
+ _type = 111
+ _pack_ = 1
+ _fields_ = [
+ ("nwqid", c_uint16),
+ ]
+
+ def cdrmap (self):
+ """
+ Returns the map of the message tail:
+ * qid ```p9qid``` * nwqid.
+ """
+ return [("qid", p9qid, nwqid)]
+
+
+class Tattach (Structure):
+ """
+ 9P type 104 'attach' request (transmit) message class
+ Attach, auth - messages to establish a connection
+ """
+ _type = 104
+ _pack_ = 1
+ _fields_ = [
+ ("fid", c_uint32),
+ ("afid", c_uint32),
+ ]
+
+ def cdrmap (self):
+ """
+ Returns the map of the message tail:
+ * uname ```p9msgstring```;
+ * aname ```p9msgstring```.
+ """
+ return [("uname", p9msgstring, 1), ("aname", p9msgstring, 1)]
+
+class Rattach (Structure):
+ """
+ 9P type 105 'attach' reply (return) message class
+ Attach, auth - messages to establish a connection
+ """
+ _type = 105
+ _pack_ = 1
+ _fields_ = [
+ ("qid", p9qid),
+ ]
+
+
+class Twstat (Structure):
+ """
+ 9P type 126 'wstat' request (transmit) message class
+ Stat, wstat - inquire or change file attributes
+ """
+ _type = 126
+ _pack_ = 1
+ _fields_ = [
+ ("fid", c_uint32),
+ ]
+
+ def cdrmap (self):
+ """
+ Returns the ``p9msgarray`` as the type of the message tail ``stat``
+ """
+ return [("stat", p9msgarray, 1)]
+
+class Rwstat (Structure):
+ """
+ 9P type 127 'wstat' reply (return) message class
+ Stat, wstat - inquire or change file attributes
+ """
+ _type = 127
+
+
+class Twrite (Structure):
+ """
+ 9P type 118 'write' request (transmit) message class
+ Read, write - transfer data from and to a file
+ """
+ _type = 118
+ _pack_ = 1
+ _fields_ = [
+ ("fid", c_uint32),
+ ("offset", c_uint64),
+ ("count", c_uint32),
+ ]
+
+ def cdrmap (self):
+ """
+ Returns the ``(c_ubyte * count)`` as the type of the message tail ``data``
+ """
+ return [("data", (c_ubyte * count), 1)]
+
+class Rwrite (Structure):
+ """
+ 9P type 119 'write' reply (return) message class
+ Read, write - transfer data from and to a file
+ """
+ _type = 119
+ _pack_ = 1
+ _fields_ = [
+ ("count", c_uint32),
+ ]
+
+# The tuple of all defined message classes
+p9msgclasses = tuple()
+p9msgclasses += tuple([None]*100) # Types for 0..99 are not defined
+p9msgclasses += tuple([Tversion, Rversion]) # 100, 101
+p9msgclasses += tuple([Tauth, Rauth]) # 102, 103
+p9msgclasses += tuple([Tattach, Rattach]) # 104, 105
+p9msgclasses += tuple([Terror, Rerror]) # 106, 107
+p9msgclasses += tuple([Tflush, Rflush]) # 108, 109
+p9msgclasses += tuple([Twalk, Rwalk]) # 110, 111
+p9msgclasses += tuple([Topen, Ropen]) # 112, 113
+p9msgclasses += tuple([Tcreate, Rcreate]) # 114, 115
+p9msgclasses += tuple([Tread, Rread]) # 116, 117
+p9msgclasses += tuple([Twrite, Rwrite]) # 118, 119
+p9msgclasses += tuple([Tclunk, Rclunk]) # 120, 121
+p9msgclasses += tuple([Tremove, Rremove]) # 122, 123
+p9msgclasses += tuple([Tstat, Rstat]) # 124, 125
+p9msgclasses += tuple([Twstat, Rwstat]) # 126, 127
+p9msgclasses += tuple([None]*128) # Types for 128..255 are not defined
+
+__all__ += ["p9msgclasses"]
+# Export some constants
+__all__ += ["VERSION9P"]
+# Export all defined message types
+__all__ += ["Tversion", "Rversion", "Tauth", "Rauth", "Tattach", "Rattach", "Terror", "Rerror", "Tflush", "Rflush", "Twalk", "Rwalk", "Topen", "Ropen", "Tcreate", "Rcreate", "Tread", "Rread", "Twrite", "Rwrite", "Tclunk", "Rclunk", "Tremove", "Rremove", "Tstat", "Rstat", "Twstat", "Rwstat"]
Something went wrong with that request. Please try again.