/*
* Copyright (c) Likewise Software. All rights Reserved.
*
* This library is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation; either version 2.1 of the license, or (at
* your option) any later version.
*
* This library 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 Lesser
* General Public License for more details. You should have received a copy
* of the GNU Lesser General Public License along with this program. If
* not, see .
*
* LIKEWISE SOFTWARE MAKES THIS SOFTWARE AVAILABLE UNDER OTHER LICENSING
* TERMS AS WELL. IF YOU HAVE ENTERED INTO A SEPARATE LICENSE AGREEMENT
* WITH LIKEWISE SOFTWARE, THEN YOU MAY ELECT TO USE THE SOFTWARE UNDER THE
* TERMS OF THAT SOFTWARE LICENSE AGREEMENT INSTEAD OF THE TERMS OF THE GNU
* LESSER GENERAL PUBLIC LICENSE, NOTWITHSTANDING THE ABOVE NOTICE. IF YOU
* HAVE QUESTIONS, OR WISH TO REQUEST A COPY OF THE ALTERNATE LICENSING
* TERMS OFFERED BY LIKEWISE SOFTWARE, PLEASE CONTACT LIKEWISE SOFTWARE AT
* license@likewisesoftware.com
*/
/*
* Module Name:
*
* example_fserv_source.doxy
*
* Abstract:
*
* Fserv source code walkthrough documentation page
*
* Authors: Brian Koropoff (bkoropoff@likewisesoftware.com)
*
*/
/**
@page example_fserv_source Source Code Walkthrough
@section common Common
Creating a message protocol requires the following:
- A set of C data structures for exchanging information
- A corresponding set of type specifications which describe
the layout and relationships of these structure
- A protocol specification which binds a set of message tags
and payload types together into a description of the protocol
Because these elements are the same for both the client and server,
they should be factored out into their own library in order to
reduce memory usage at runtime.
The file include/protocol.h contains the basic C type
definitions and message type enumeration for the Fserv message
protocol. The type and protocol specifications are contained
in src/protocol.c.
@subsection phs Message Structures
First, we define the types that will be used to transmit data
between client and server:
@dontinclude fserv/include/protocol.h
@skip Begin message structures
@until End message structures
Note the presence of the opaque FileHandle structure.
This type will be transmitted to the client as a handle. By
placing the structure definition in a separate header, the C compiler
can ensure that the client does not attempt to dereference
proxies while also enforcing type safety. The server will include
protocol-server.h so that it can create and manipulate
its handles. This technique is not necessary for the security of
the server but is a good practice to catch potential bugs.
Also note that there are no OpenReply or CloseRequest
structures. This is because both can be represented as FileHandles
without being wrapped in an outer structure -- LWMsg permits any
pointer or pointer-like type to be the payload of a message.
@subsection mte Message Tag Enumeration
We then enumerates all possible message tags. These tags
comprise the set of messages that may be sent between client and
server. Each element of the enumeration has a comment specifying
the C structure which is the payload for that type of message.
@skip Begin message enumeration
@until End message enumeration
For clarity, we organize messages into blocks of 3. The first
message is the request sent to the server. The second and third
are the success and error messages sent in response to the client.
LWMsg does not impose limitations on when certain message types
can be sent or by whom. Although LWMsg guarantees that all
message payloads are well-formed, it is up to the application
to ensure that they are used appropriately and in the correct
sequence. Future versions may support encoding some restrictions
directly into the protocol specification.
@subsection ts Type Specification
Each C structure that we want to use in the message protocol must
have a type specification describing it:
@dontinclude fserv/src/protocol.c
@skip Begin type specifications
@until End type specifications
@subsection ps Protocol Specification
Finally, we need a protocol specification which binds together
our enumerated set of messages tags and indicates the payload
type of each message.
@skip Begin protocol specification
@until End protocol specification
@section c Client
The client API implementation is contained in src/fserv.c.
It abstracts away the details of creating connections and exchanging
messages in order to perform Fserv operations.
@subsection connect Connecting
Connections are created to the server by fserv_connect().
Before establishing the connection, the function must first create
a protocol object if it has not already. A protocol object allows
one or more protocol specifications to be combined together. This
protocol object is what is then used to create a connection. First,
a new protocol object is created.
@dontinclude fserv/src/fserv.c
@skip Create protocol object
@until ;
The protocol specification is then added to the object.
@skip Add protocol spec
@until ;
After ensuring that a protocol object has been created, the function
then establishes the actual connection. This is done in two steps.
First, it creates a new connection object:
@skip Create connection
@until ;
Connections are merely a type of association, so "association"
and "connection" will be used interchangably for the remainder of this
document.
Next, it sets the connection mode and endpoint:
@skip Set connection endpoint
@until ;
The connection mode, #LWMSG_CONNECTION_MODE_LOCAL, indicates a UNIX domain
socket connection. The endpoint is the path of the special socket file.
After the endpoint is set, the association with the server can be established:
@skip Establish session
@until ;
@subsection discon Disconnecting
To disconnect from the server, the client simply closes the association
inside fserv_disconnect():
@skip Close association
@until ;
This operation attempts to cleanly tear down the connection with the
server and may fail. Whether it succeeds or fails, the function deletes
the association before returning:
@skip Delete association
@until ;
Deleting an association does not cleanly tear down the connection if
it has not been closed, but it is guaranteed to succeed and release
all resources that were being held. The sequence of #lwmsg_assoc_close()
followed by #lwmsg_assoc_delete() is the preferred way to shut down
a connection.
@subsection open Opening a File
Opening a file involves sending a request message to the server and
receiving a response back that contains a file handle. The function
fserv_open() begins by filling out the OpenRequest
structure that it will send:
@skip Set up
@until ;
@until ;
@until ;
@until ;
The function then sends the message and receives a reply in a single
transact operation:
@skip Send message
@until ;
If the transaction succeeds, reply_msg.tag is set to the tag
of the reply message and reply_msg.data is set to the unmarshalled
message payload. The function then checks what kind of reply it received.
If it received a success message, it allocates a wrapper around the
handle it received and returns that to the caller. If it received a failure
message, it extracts the error code and returns the error to the caller.
Otherwise, it indicates that it received an invalid message type.
@skip switch
@until default:
@until }
@section s Server
**/