Skip to content

Commit

Permalink
Use Message Context (go-ldap#69)
Browse files Browse the repository at this point in the history
This patch introduces a new type called `messageContext` which is now the
return value of `(*Conn).sendMessage()`. The message context object still
contains a channel from which methods like, Add(), Bind(), Search(), etc.,
will receive response packets. It also has a field which holds the message
ID as well as a `done` channel which is used to prevent deadlock in the
`processMessages()` goroutine.

This is accomplished by also changing the `(*Conn).finishMessage()` method to
take a message context and close this `done` channel before sending a
`MessageFinish` packet to the `processMessages()` goroutine.

The `processMessages()` goroutine now has a `messageContexts` map which
replaces the `chanResults` map. Now, rather than sending response packets only
on the response channels, the `messageContext` has its own `sendResponse()`
method which uses a switch that blocks on sending a response packet *or*
waiting for its `done` channel to be closed by `finishMessage()`.

Docker-DCO-1.1-Signed-off-by: Josh Hawn <[email protected]> (github: jlhawn)
  • Loading branch information
jlhawn authored and liggitt committed Jun 29, 2016
1 parent 8a8cb05 commit 248a318
Show file tree
Hide file tree
Showing 9 changed files with 416 additions and 147 deletions.
23 changes: 8 additions & 15 deletions add.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,6 @@ type Attribute struct {
Vals []string
}



func (a *Attribute) encode() *ber.Packet {
seq := ber.Encode(ber.ClassUniversal, ber.TypeConstructed, ber.TagSequence, nil, "Attribute")
seq.AppendChild(ber.NewString(ber.ClassUniversal, ber.TypePrimitive, ber.TagOctetString, a.Type, "Type"))
Expand All @@ -39,7 +37,6 @@ type AddRequest struct {
Attributes []Attribute
}


func (a AddRequest) encode() *ber.Packet {
request := ber.Encode(ber.ClassApplication, ber.TypeConstructed, ApplicationAddRequest, nil, "Add Request")
request.AppendChild(ber.NewString(ber.ClassUniversal, ber.TypePrimitive, ber.TagOctetString, a.DN, "DN"))
Expand All @@ -63,29 +60,25 @@ func NewAddRequest(dn string) *AddRequest {
}

func (l *Conn) Add(addRequest *AddRequest) error {
messageID := l.nextMessageID()
packet := ber.Encode(ber.ClassUniversal, ber.TypeConstructed, ber.TagSequence, nil, "LDAP Request")
packet.AppendChild(ber.NewInteger(ber.ClassUniversal, ber.TypePrimitive, ber.TagInteger, messageID, "MessageID"))
packet.AppendChild(ber.NewInteger(ber.ClassUniversal, ber.TypePrimitive, ber.TagInteger, l.nextMessageID(), "MessageID"))
packet.AppendChild(addRequest.encode())

l.Debug.PrintPacket(packet)

channel, err := l.sendMessage(packet)
msgCtx, err := l.sendMessage(packet)
if err != nil {
return err
}
if channel == nil {
return NewError(ErrorNetwork, errors.New("ldap: could not send message"))
}
defer l.finishMessage(messageID)
defer l.finishMessage(msgCtx)

l.Debug.Printf("%d: waiting for response", messageID)
packetResponse, ok := <-channel
l.Debug.Printf("%d: waiting for response", msgCtx.id)
packetResponse, ok := <-msgCtx.responses
if !ok {
return NewError(ErrorNetwork, errors.New("ldap: channel closed"))
return NewError(ErrorNetwork, errors.New("ldap: response channel closed"))
}
packet, err = packetResponse.ReadPacket()
l.Debug.Printf("%d: got response %p", messageID, packet)
l.Debug.Printf("%d: got response %p", msgCtx.id, packet)
if err != nil {
return err
}
Expand All @@ -106,6 +99,6 @@ func (l *Conn) Add(addRequest *AddRequest) error {
log.Printf("Unexpected Response: %d", packet.Children[1].Tag)
}

l.Debug.Printf("%d: returning", messageID)
l.Debug.Printf("%d: returning", msgCtx.id)
return nil
}
34 changes: 12 additions & 22 deletions bind.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,32 +40,27 @@ func (bindRequest *SimpleBindRequest) encode() *ber.Packet {
}

func (l *Conn) SimpleBind(simpleBindRequest *SimpleBindRequest) (*SimpleBindResult, error) {
messageID := l.nextMessageID()

packet := ber.Encode(ber.ClassUniversal, ber.TypeConstructed, ber.TagSequence, nil, "LDAP Request")
packet.AppendChild(ber.NewInteger(ber.ClassUniversal, ber.TypePrimitive, ber.TagInteger, messageID, "MessageID"))
packet.AppendChild(ber.NewInteger(ber.ClassUniversal, ber.TypePrimitive, ber.TagInteger, l.nextMessageID(), "MessageID"))
encodedBindRequest := simpleBindRequest.encode()
packet.AppendChild(encodedBindRequest)

if l.Debug {
ber.PrintPacket(packet)
}

channel, err := l.sendMessage(packet)
msgCtx, err := l.sendMessage(packet)
if err != nil {
return nil, err
}
if channel == nil {
return nil, NewError(ErrorNetwork, errors.New("ldap: could not send message"))
}
defer l.finishMessage(messageID)
defer l.finishMessage(msgCtx)

packetResponse, ok := <-channel
packetResponse, ok := <-msgCtx.responses
if !ok {
return nil, NewError(ErrorNetwork, errors.New("ldap: channel closed"))
return nil, NewError(ErrorNetwork, errors.New("ldap: response channel closed"))
}
packet, err = packetResponse.ReadPacket()
l.Debug.Printf("%d: got response %p", messageID, packet)
l.Debug.Printf("%d: got response %p", msgCtx.id, packet)
if err != nil {
return nil, err
}
Expand Down Expand Up @@ -96,10 +91,8 @@ func (l *Conn) SimpleBind(simpleBindRequest *SimpleBindRequest) (*SimpleBindResu
}

func (l *Conn) Bind(username, password string) error {
messageID := l.nextMessageID()

packet := ber.Encode(ber.ClassUniversal, ber.TypeConstructed, ber.TagSequence, nil, "LDAP Request")
packet.AppendChild(ber.NewInteger(ber.ClassUniversal, ber.TypePrimitive, ber.TagInteger, messageID, "MessageID"))
packet.AppendChild(ber.NewInteger(ber.ClassUniversal, ber.TypePrimitive, ber.TagInteger, l.nextMessageID(), "MessageID"))
bindRequest := ber.Encode(ber.ClassApplication, ber.TypeConstructed, ApplicationBindRequest, nil, "Bind Request")
bindRequest.AppendChild(ber.NewInteger(ber.ClassUniversal, ber.TypePrimitive, ber.TagInteger, 3, "Version"))
bindRequest.AppendChild(ber.NewString(ber.ClassUniversal, ber.TypePrimitive, ber.TagOctetString, username, "User Name"))
Expand All @@ -110,21 +103,18 @@ func (l *Conn) Bind(username, password string) error {
ber.PrintPacket(packet)
}

channel, err := l.sendMessage(packet)
msgCtx, err := l.sendMessage(packet)
if err != nil {
return err
}
if channel == nil {
return NewError(ErrorNetwork, errors.New("ldap: could not send message"))
}
defer l.finishMessage(messageID)
defer l.finishMessage(msgCtx)

packetResponse, ok := <-channel
packetResponse, ok := <-msgCtx.responses
if !ok {
return NewError(ErrorNetwork, errors.New("ldap: channel closed"))
return NewError(ErrorNetwork, errors.New("ldap: response channel closed"))
}
packet, err = packetResponse.ReadPacket()
l.Debug.Printf("%d: got response %p", messageID, packet)
l.Debug.Printf("%d: got response %p", msgCtx.id, packet)
if err != nil {
return err
}
Expand Down
18 changes: 7 additions & 11 deletions compare.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,9 +33,8 @@ import (
// Compare checks to see if the attribute of the dn matches value. Returns true if it does otherwise
// false with any error that occurs if any.
func (l *Conn) Compare(dn, attribute, value string) (bool, error) {
messageID := l.nextMessageID()
packet := ber.Encode(ber.ClassUniversal, ber.TypeConstructed, ber.TagSequence, nil, "LDAP Request")
packet.AppendChild(ber.NewInteger(ber.ClassUniversal, ber.TypePrimitive, ber.TagInteger, messageID, "MessageID"))
packet.AppendChild(ber.NewInteger(ber.ClassUniversal, ber.TypePrimitive, ber.TagInteger, l.nextMessageID(), "MessageID"))

request := ber.Encode(ber.ClassApplication, ber.TypeConstructed, ApplicationCompareRequest, nil, "Compare Request")
request.AppendChild(ber.NewString(ber.ClassUniversal, ber.TypePrimitive, ber.TagOctetString, dn, "DN"))
Expand All @@ -48,22 +47,19 @@ func (l *Conn) Compare(dn, attribute, value string) (bool, error) {

l.Debug.PrintPacket(packet)

channel, err := l.sendMessage(packet)
msgCtx, err := l.sendMessage(packet)
if err != nil {
return false, err
}
if channel == nil {
return false, NewError(ErrorNetwork, errors.New("ldap: could not send message"))
}
defer l.finishMessage(messageID)
defer l.finishMessage(msgCtx)

l.Debug.Printf("%d: waiting for response", messageID)
packetResponse, ok := <-channel
l.Debug.Printf("%d: waiting for response", msgCtx.id)
packetResponse, ok := <-msgCtx.responses
if !ok {
return false, NewError(ErrorNetwork, errors.New("ldap: channel closed"))
return false, NewError(ErrorNetwork, errors.New("ldap: response channel closed"))
}
packet, err = packetResponse.ReadPacket()
l.Debug.Printf("%d: got response %p", messageID, packet)
l.Debug.Printf("%d: got response %p", msgCtx.id, packet)
if err != nil {
return false, err
}
Expand Down
Loading

0 comments on commit 248a318

Please sign in to comment.