<commit_before>// Copyright 2009 The Go Authors.  All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package srv

import (
	"code.google.com/p/go9p/p"
)

func (srv *Srv) version(req *Req) {
	tc := req.Tc
	conn := req.Conn

	if tc.Msize < p.IOHDRSZ {
		req.RespondError(&p.Error{"msize too small", p.EINVAL})
		return
	}

	if tc.Msize < conn.Msize {
		conn.Msize = tc.Msize
	}

	conn.Dotu = tc.Version == "9P2000.u" && srv.Dotu
	ver := "9P2000"
	if conn.Dotu {
		ver = "9P2000.u"
	}

	/* make sure that the responses of all current requests will be ignored */
	conn.Lock()
	for tag, r := range conn.reqs {
		if tag == p.NOTAG {
			continue
		}

		for rr := r; rr != nil; rr = rr.next {
			rr.Lock()
			rr.status |= reqFlush
			rr.Unlock()
		}
	}
	conn.Unlock()

	req.RespondRversion(conn.Msize, ver)
}

func (srv *Srv) auth(req *Req) {
	tc := req.Tc
	conn := req.Conn
	if tc.Afid == p.NOFID {
		req.RespondError(Eunknownfid)
		return
	}

	req.Afid = conn.FidNew(tc.Afid)
	if req.Afid == nil {
		req.RespondError(Einuse)
		return
	}

	var user p.User = nil
	if tc.Unamenum != p.NOUID || conn.Dotu {
		user = srv.Upool.Uid2User(int(tc.Unamenum))
	} else if tc.Uname != "" {
		user = srv.Upool.Uname2User(tc.Uname)
	}

	if user == nil {
		req.RespondError(Enouser)
		return
	}

	req.Afid.User = user
	req.Afid.Type = p.QTAUTH
	if aop, ok := (srv.ops).(AuthOps); ok {
		aqid, err := aop.AuthInit(req.Afid, tc.Aname)
		if err != nil {
			req.RespondError(err)
		} else {
			aqid.Type |= p.QTAUTH // just in case
			req.RespondRauth(aqid)
		}
	} else {
		req.RespondError(Enoauth)
	}

}

func (srv *Srv) authPost(req *Req) {
	if req.Rc != nil && req.Rc.Type == p.Rattach {
		req.Afid.IncRef()
	}
}

func (srv *Srv) attach(req *Req) {
	tc := req.Tc
	conn := req.Conn
	if tc.Fid == p.NOFID {
		req.RespondError(Eunknownfid)
		return
	}

	req.Fid = conn.FidNew(tc.Fid)
	if req.Fid == nil {
		req.RespondError(Einuse)
		return
	}

	if tc.Afid != p.NOFID {
		req.Afid = conn.FidGet(tc.Afid)
		if req.Afid == nil {
			req.RespondError(Eunknownfid)
		}
	}

	var user p.User = nil
	if tc.Unamenum != p.NOUID || conn.Dotu {
		user = srv.Upool.Uid2User(int(tc.Unamenum))
	} else if tc.Uname != "" {
		user = srv.Upool.Uname2User(tc.Uname)
	}

	if user == nil {
		req.RespondError(Enouser)
		return
	}

	req.Fid.User = user
	if aop, ok := (srv.ops).(AuthOps); ok {
		err := aop.AuthCheck(req.Fid, req.Afid, tc.Aname)
		if err != nil {
			req.RespondError(err)
			return
		}
	}

	(srv.ops).(ReqOps).Attach(req)
}

func (srv *Srv) attachPost(req *Req) {
	if req.Rc != nil && req.Rc.Type == p.Rattach {
		req.Fid.Type = req.Rc.Qid.Type
		req.Fid.IncRef()
	}
}

func (srv *Srv) flush(req *Req) {
	conn := req.Conn
	tag := req.Tc.Oldtag
	p.PackRflush(req.Rc)
	conn.Lock()
	r := conn.reqs[tag]
	if r != nil {
		req.flushreq = r.flushreq
		r.flushreq = req
	}
	conn.Unlock()

	if r == nil {
		// there are no requests with that tag
		req.Respond()
		return
	}

	r.Lock()
	status := r.status
	if (status & (reqWork | reqSaved)) == 0 {
		/* the request is not worked on yet */
		r.status |= reqFlush
	}
	r.Unlock()

	if (status & (reqWork | reqSaved)) == 0 {
		r.Respond()
	} else {
		if op, ok := (srv.ops).(FlushOp); ok {
			op.Flush(r)
		}
	}
}

func (srv *Srv) walk(req *Req) {
	conn := req.Conn
	tc := req.Tc
	fid := req.Fid

	/* we can't walk regular files, only clone them */
	if len(tc.Wname) > 0 && (fid.Type&p.QTDIR) == 0 {
		req.RespondError(Enotdir)
		return
	}

	/* we can't walk open files */
	if fid.opened {
		req.RespondError(Ebaduse)
		return
	}

	if tc.Fid != tc.Newfid {
		req.Newfid = conn.FidNew(tc.Newfid)
		if req.Newfid == nil {
			req.RespondError(Einuse)
			return
		}

		req.Newfid.User = fid.User
		req.Newfid.Type = fid.Type
	} else {
		req.Newfid = req.Fid
		req.Newfid.IncRef()
	}

	(req.Conn.Srv.ops).(ReqOps).Walk(req)
}

func (srv *Srv) walkPost(req *Req) {
	rc := req.Rc
	if rc == nil || rc.Type != p.Rwalk || req.Newfid == nil {
		return
	}

	n := len(rc.Wqid)
	if n > 0 {
		req.Newfid.Type = rc.Wqid[n-1].Type
	} else {
		req.Newfid.Type = req.Fid.Type
	}

	if req.Newfid.fid != req.Fid.fid {
		req.Newfid.IncRef()
	}
}

func (srv *Srv) open(req *Req) {
	fid := req.Fid
	tc := req.Tc
	if fid.opened {
		req.RespondError(Eopen)
		return
	}

	if (fid.Type&p.QTDIR) != 0 && tc.Mode != p.OREAD {
		req.RespondError(Eperm)
		return
	}

	fid.Omode = tc.Mode
	(req.Conn.Srv.ops).(ReqOps).Open(req)
}

func (srv *Srv) openPost(req *Req) {
	if req.Fid != nil {
		req.Fid.opened = req.Rc != nil && req.Rc.Type == p.Ropen
	}
}

func (srv *Srv) create(req *Req) {
	fid := req.Fid
	tc := req.Tc
	if fid.opened {
		req.RespondError(Eopen)
		return
	}

	if (fid.Type & p.QTDIR) == 0 {
		req.RespondError(Enotdir)
		return
	}

	/* can't open directories for other than reading */
	if (tc.Perm&p.DMDIR) != 0 && tc.Mode != p.OREAD {
		req.RespondError(Eperm)
		return
	}

	/* can't create special files if not 9P2000.u */
	if (tc.Perm&(p.DMNAMEDPIPE|p.DMSYMLINK|p.DMLINK|p.DMDEVICE|p.DMSOCKET)) != 0 && !req.Conn.Dotu {
		req.RespondError(Eperm)
		return
	}

	fid.Omode = tc.Mode
	(req.Conn.Srv.ops).(ReqOps).Create(req)
}

func (srv *Srv) createPost(req *Req) {
	if req.Rc != nil && req.Rc.Type == p.Rcreate && req.Fid != nil {
		req.Fid.Type = req.Rc.Qid.Type
		req.Fid.opened = true
	}
}

func (srv *Srv) read(req *Req) {
	tc := req.Tc
	fid := req.Fid
	if tc.Count+p.IOHDRSZ > req.Conn.Msize {
		req.RespondError(Etoolarge)
		return
	}

	if (fid.Type & p.QTAUTH) != 0 {
		var n int

		rc := req.Tc
		err := p.InitRread(rc, tc.Count)
		if err != nil {
			req.RespondError(err)
			return
		}

		if op, ok := (req.Conn.Srv.ops).(AuthOps); ok {
			n, err = op.AuthRead(fid, tc.Offset, rc.Data)
			if err != nil {
				req.RespondError(err)
				return
			}

			p.SetRreadCount(rc, uint32(n))
			req.Respond()
		} else {
			req.RespondError(Enotimpl)
		}

		return
	}

	if (fid.Type & p.QTDIR) != 0 {
		if tc.Offset == 0 {
			fid.Diroffset = 0
		} else if tc.Offset != fid.Diroffset {
			req.RespondError(Ebadoffset)
			return
		}
	}

	(req.Conn.Srv.ops).(ReqOps).Read(req)
}

func (srv *Srv) readPost(req *Req) {
	if req.Rc != nil && req.Rc.Type == p.Rread && (req.Fid.Type&p.QTDIR) != 0 {
		req.Fid.Diroffset += uint64(req.Rc.Count)
	}
}

func (srv *Srv) write(req *Req) {
	fid := req.Fid
	tc := req.Tc
	if (fid.Type & p.QTAUTH) != 0 {
		tc := req.Tc
		if op, ok := (req.Conn.Srv.ops).(AuthOps); ok {
			n, err := op.AuthWrite(req.Fid, tc.Offset, tc.Data)
			if err != nil {
				req.RespondError(err)
			} else {
				req.RespondRwrite(uint32(n))
			}
		} else {
			req.RespondError(Enotimpl)
		}

		return
	}

	if !fid.opened || (fid.Type&p.QTDIR) != 0 || (fid.Omode&3) == p.OREAD {
		req.RespondError(Ebaduse)
		return
	}

	if tc.Count+p.IOHDRSZ > req.Conn.Msize {
		req.RespondError(Etoolarge)
		return
	}

	(req.Conn.Srv.ops).(ReqOps).Write(req)
}

func (srv *Srv) clunk(req *Req) {
	fid := req.Fid
	if (fid.Type & p.QTAUTH) != 0 {
		if op, ok := (req.Conn.Srv.ops).(AuthOps); ok {
			op.AuthDestroy(fid)
			req.RespondRclunk()
		} else {
			req.RespondError(Enotimpl)
		}

		return
	}

	(req.Conn.Srv.ops).(ReqOps).Clunk(req)
}

func (srv *Srv) clunkPost(req *Req) {
	if req.Rc != nil && req.Rc.Type == p.Rclunk && req.Fid != nil {
		req.Fid.DecRef()
	}
}

func (srv *Srv) remove(req *Req) { (req.Conn.Srv.ops).(ReqOps).Remove(req) }

func (srv *Srv) removePost(req *Req) {
	if req.Rc != nil && req.Fid != nil {
		req.Fid.DecRef()
	}
}

func (srv *Srv) stat(req *Req) { (req.Conn.Srv.ops).(ReqOps).Stat(req) }

func (srv *Srv) wstat(req *Req) {
	/*
		fid := req.Fid
		d := &req.Tc.Dir
		if d.Type != uint16(0xFFFF) || d.Dev != uint32(0xFFFFFFFF) || d.Version != uint32(0xFFFFFFFF) ||
			d.Path != uint64(0xFFFFFFFFFFFFFFFF) {
			req.RespondError(Eperm)
			return
		}

		if (d.Mode != 0xFFFFFFFF) && (((fid.Type&p.QTDIR) != 0 && (d.Mode&p.DMDIR) == 0) ||
			((d.Type&p.QTDIR) == 0 && (d.Mode&p.DMDIR) != 0)) {
			req.RespondError(Edirchange)
			return
		}
	*/

	(req.Conn.Srv.ops).(ReqOps).Wstat(req)
}
<commit_msg>When walks succeed only partially, don't keep the new fid.<commit_after>// Copyright 2009 The Go Authors.  All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package srv

import (
	"code.google.com/p/go9p/p"
)

func (srv *Srv) version(req *Req) {
	tc := req.Tc
	conn := req.Conn

	if tc.Msize < p.IOHDRSZ {
		req.RespondError(&p.Error{"msize too small", p.EINVAL})
		return
	}

	if tc.Msize < conn.Msize {
		conn.Msize = tc.Msize
	}

	conn.Dotu = tc.Version == "9P2000.u" && srv.Dotu
	ver := "9P2000"
	if conn.Dotu {
		ver = "9P2000.u"
	}

	/* make sure that the responses of all current requests will be ignored */
	conn.Lock()
	for tag, r := range conn.reqs {
		if tag == p.NOTAG {
			continue
		}

		for rr := r; rr != nil; rr = rr.next {
			rr.Lock()
			rr.status |= reqFlush
			rr.Unlock()
		}
	}
	conn.Unlock()

	req.RespondRversion(conn.Msize, ver)
}

func (srv *Srv) auth(req *Req) {
	tc := req.Tc
	conn := req.Conn
	if tc.Afid == p.NOFID {
		req.RespondError(Eunknownfid)
		return
	}

	req.Afid = conn.FidNew(tc.Afid)
	if req.Afid == nil {
		req.RespondError(Einuse)
		return
	}

	var user p.User = nil
	if tc.Unamenum != p.NOUID || conn.Dotu {
		user = srv.Upool.Uid2User(int(tc.Unamenum))
	} else if tc.Uname != "" {
		user = srv.Upool.Uname2User(tc.Uname)
	}

	if user == nil {
		req.RespondError(Enouser)
		return
	}

	req.Afid.User = user
	req.Afid.Type = p.QTAUTH
	if aop, ok := (srv.ops).(AuthOps); ok {
		aqid, err := aop.AuthInit(req.Afid, tc.Aname)
		if err != nil {
			req.RespondError(err)
		} else {
			aqid.Type |= p.QTAUTH // just in case
			req.RespondRauth(aqid)
		}
	} else {
		req.RespondError(Enoauth)
	}

}

func (srv *Srv) authPost(req *Req) {
	if req.Rc != nil && req.Rc.Type == p.Rattach {
		req.Afid.IncRef()
	}
}

func (srv *Srv) attach(req *Req) {
	tc := req.Tc
	conn := req.Conn
	if tc.Fid == p.NOFID {
		req.RespondError(Eunknownfid)
		return
	}

	req.Fid = conn.FidNew(tc.Fid)
	if req.Fid == nil {
		req.RespondError(Einuse)
		return
	}

	if tc.Afid != p.NOFID {
		req.Afid = conn.FidGet(tc.Afid)
		if req.Afid == nil {
			req.RespondError(Eunknownfid)
		}
	}

	var user p.User = nil
	if tc.Unamenum != p.NOUID || conn.Dotu {
		user = srv.Upool.Uid2User(int(tc.Unamenum))
	} else if tc.Uname != "" {
		user = srv.Upool.Uname2User(tc.Uname)
	}

	if user == nil {
		req.RespondError(Enouser)
		return
	}

	req.Fid.User = user
	if aop, ok := (srv.ops).(AuthOps); ok {
		err := aop.AuthCheck(req.Fid, req.Afid, tc.Aname)
		if err != nil {
			req.RespondError(err)
			return
		}
	}

	(srv.ops).(ReqOps).Attach(req)
}

func (srv *Srv) attachPost(req *Req) {
	if req.Rc != nil && req.Rc.Type == p.Rattach {
		req.Fid.Type = req.Rc.Qid.Type
		req.Fid.IncRef()
	}
}

func (srv *Srv) flush(req *Req) {
	conn := req.Conn
	tag := req.Tc.Oldtag
	p.PackRflush(req.Rc)
	conn.Lock()
	r := conn.reqs[tag]
	if r != nil {
		req.flushreq = r.flushreq
		r.flushreq = req
	}
	conn.Unlock()

	if r == nil {
		// there are no requests with that tag
		req.Respond()
		return
	}

	r.Lock()
	status := r.status
	if (status & (reqWork | reqSaved)) == 0 {
		/* the request is not worked on yet */
		r.status |= reqFlush
	}
	r.Unlock()

	if (status & (reqWork | reqSaved)) == 0 {
		r.Respond()
	} else {
		if op, ok := (srv.ops).(FlushOp); ok {
			op.Flush(r)
		}
	}
}

func (srv *Srv) walk(req *Req) {
	conn := req.Conn
	tc := req.Tc
	fid := req.Fid

	/* we can't walk regular files, only clone them */
	if len(tc.Wname) > 0 && (fid.Type&p.QTDIR) == 0 {
		req.RespondError(Enotdir)
		return
	}

	/* we can't walk open files */
	if fid.opened {
		req.RespondError(Ebaduse)
		return
	}

	if tc.Fid != tc.Newfid {
		req.Newfid = conn.FidNew(tc.Newfid)
		if req.Newfid == nil {
			req.RespondError(Einuse)
			return
		}

		req.Newfid.User = fid.User
		req.Newfid.Type = fid.Type
	} else {
		req.Newfid = req.Fid
		req.Newfid.IncRef()
	}

	(req.Conn.Srv.ops).(ReqOps).Walk(req)
}

func (srv *Srv) walkPost(req *Req) {
	rc := req.Rc
	if rc == nil || rc.Type != p.Rwalk || req.Newfid == nil {
		return
	}

	n := len(rc.Wqid)
	if n > 0 {
		req.Newfid.Type = rc.Wqid[n-1].Type
	} else {
		req.Newfid.Type = req.Fid.Type
	}

	// Don't retain the fid if only a partial walk succeeded
	if n != len(req.Tc.Wname) {
		return
	}

	if req.Newfid.fid != req.Fid.fid {
		req.Newfid.IncRef()
	}
}

func (srv *Srv) open(req *Req) {
	fid := req.Fid
	tc := req.Tc
	if fid.opened {
		req.RespondError(Eopen)
		return
	}

	if (fid.Type&p.QTDIR) != 0 && tc.Mode != p.OREAD {
		req.RespondError(Eperm)
		return
	}

	fid.Omode = tc.Mode
	(req.Conn.Srv.ops).(ReqOps).Open(req)
}

func (srv *Srv) openPost(req *Req) {
	if req.Fid != nil {
		req.Fid.opened = req.Rc != nil && req.Rc.Type == p.Ropen
	}
}

func (srv *Srv) create(req *Req) {
	fid := req.Fid
	tc := req.Tc
	if fid.opened {
		req.RespondError(Eopen)
		return
	}

	if (fid.Type & p.QTDIR) == 0 {
		req.RespondError(Enotdir)
		return
	}

	/* can't open directories for other than reading */
	if (tc.Perm&p.DMDIR) != 0 && tc.Mode != p.OREAD {
		req.RespondError(Eperm)
		return
	}

	/* can't create special files if not 9P2000.u */
	if (tc.Perm&(p.DMNAMEDPIPE|p.DMSYMLINK|p.DMLINK|p.DMDEVICE|p.DMSOCKET)) != 0 && !req.Conn.Dotu {
		req.RespondError(Eperm)
		return
	}

	fid.Omode = tc.Mode
	(req.Conn.Srv.ops).(ReqOps).Create(req)
}

func (srv *Srv) createPost(req *Req) {
	if req.Rc != nil && req.Rc.Type == p.Rcreate && req.Fid != nil {
		req.Fid.Type = req.Rc.Qid.Type
		req.Fid.opened = true
	}
}

func (srv *Srv) read(req *Req) {
	tc := req.Tc
	fid := req.Fid
	if tc.Count+p.IOHDRSZ > req.Conn.Msize {
		req.RespondError(Etoolarge)
		return
	}

	if (fid.Type & p.QTAUTH) != 0 {
		var n int

		rc := req.Tc
		err := p.InitRread(rc, tc.Count)
		if err != nil {
			req.RespondError(err)
			return
		}

		if op, ok := (req.Conn.Srv.ops).(AuthOps); ok {
			n, err = op.AuthRead(fid, tc.Offset, rc.Data)
			if err != nil {
				req.RespondError(err)
				return
			}

			p.SetRreadCount(rc, uint32(n))
			req.Respond()
		} else {
			req.RespondError(Enotimpl)
		}

		return
	}

	if (fid.Type & p.QTDIR) != 0 {
		if tc.Offset == 0 {
			fid.Diroffset = 0
		} else if tc.Offset != fid.Diroffset {
			req.RespondError(Ebadoffset)
			return
		}
	}

	(req.Conn.Srv.ops).(ReqOps).Read(req)
}

func (srv *Srv) readPost(req *Req) {
	if req.Rc != nil && req.Rc.Type == p.Rread && (req.Fid.Type&p.QTDIR) != 0 {
		req.Fid.Diroffset += uint64(req.Rc.Count)
	}
}

func (srv *Srv) write(req *Req) {
	fid := req.Fid
	tc := req.Tc
	if (fid.Type & p.QTAUTH) != 0 {
		tc := req.Tc
		if op, ok := (req.Conn.Srv.ops).(AuthOps); ok {
			n, err := op.AuthWrite(req.Fid, tc.Offset, tc.Data)
			if err != nil {
				req.RespondError(err)
			} else {
				req.RespondRwrite(uint32(n))
			}
		} else {
			req.RespondError(Enotimpl)
		}

		return
	}

	if !fid.opened || (fid.Type&p.QTDIR) != 0 || (fid.Omode&3) == p.OREAD {
		req.RespondError(Ebaduse)
		return
	}

	if tc.Count+p.IOHDRSZ > req.Conn.Msize {
		req.RespondError(Etoolarge)
		return
	}

	(req.Conn.Srv.ops).(ReqOps).Write(req)
}

func (srv *Srv) clunk(req *Req) {
	fid := req.Fid
	if (fid.Type & p.QTAUTH) != 0 {
		if op, ok := (req.Conn.Srv.ops).(AuthOps); ok {
			op.AuthDestroy(fid)
			req.RespondRclunk()
		} else {
			req.RespondError(Enotimpl)
		}

		return
	}

	(req.Conn.Srv.ops).(ReqOps).Clunk(req)
}

func (srv *Srv) clunkPost(req *Req) {
	if req.Rc != nil && req.Rc.Type == p.Rclunk && req.Fid != nil {
		req.Fid.DecRef()
	}
}

func (srv *Srv) remove(req *Req) { (req.Conn.Srv.ops).(ReqOps).Remove(req) }

func (srv *Srv) removePost(req *Req) {
	if req.Rc != nil && req.Fid != nil {
		req.Fid.DecRef()
	}
}

func (srv *Srv) stat(req *Req) { (req.Conn.Srv.ops).(ReqOps).Stat(req) }

func (srv *Srv) wstat(req *Req) {
	/*
		fid := req.Fid
		d := &req.Tc.Dir
		if d.Type != uint16(0xFFFF) || d.Dev != uint32(0xFFFFFFFF) || d.Version != uint32(0xFFFFFFFF) ||
			d.Path != uint64(0xFFFFFFFFFFFFFFFF) {
			req.RespondError(Eperm)
			return
		}

		if (d.Mode != 0xFFFFFFFF) && (((fid.Type&p.QTDIR) != 0 && (d.Mode&p.DMDIR) == 0) ||
			((d.Type&p.QTDIR) == 0 && (d.Mode&p.DMDIR) != 0)) {
			req.RespondError(Edirchange)
			return
		}
	*/

	(req.Conn.Srv.ops).(ReqOps).Wstat(req)
}
<|endoftext|>


<commit_before>package main

import (
	"encoding/json"
	"errors"
	"flag"
	"fmt"
	"github.com/ActiveState/tail"
	"github.com/sevenscale/remote_syslog2/papertrail"
	"github.com/sevenscale/remote_syslog2/syslog"
	"github.com/sevenscale/remote_syslog2/syslog/certs"
	"io/ioutil"
	"log"
	"os"
	"path"
	"time"
)

func tailFile(file string, logger *syslog.Conn) error {
	tailConfig := tail.Config{ReOpen: true, Follow: true, MustExist: false, Location: &tail.SeekInfo{0, os.SEEK_END}}
	t, err := tail.TailFile(file, tailConfig)

	if err != nil {
		log.Println(err)
		return err
	}

	for line := range t.Lines {
		p := syslog.Packet{
			Severity: syslog.SevInfo,
			Facility: syslog.LogLocal1, // todo: customize this
			Time:     time.Now(),
			Hostname: logger.Hostname(),
			Tag:      path.Base(file),
			Message:  line.Text,
		}
		err = logger.WritePacket(p)
		if err != nil {
			return err
		}

	}

	return errors.New("Tail worker executed abnormally")
}

type ConfigFile struct {
	Files       []string
	Destination struct {
		Host     string
		Port     int
		Protocol string
	}
	CABundle string `json:"ca_bundle"`
}

func main() {
	configFile := flag.String("config", "/etc/remote_syslog2/config.json", "the configuration file")
	flag.Parse()

	// ignore error, we'll use the local addr when we connect
	hostname, _ := os.Hostname()

	log.Printf("Reading configuration file %s", *configFile)
	file, err := ioutil.ReadFile(*configFile)
	if err != nil {
		fmt.Println(err)
		os.Exit(1)
	}

	var config ConfigFile
	err = json.Unmarshal(file, &config)
	if err != nil {
		fmt.Println("The configfile is invalid: ", err)
		os.Exit(1)
	}

	destination := fmt.Sprintf("%s:%d", config.Destination.Host, config.Destination.Port)
	cabundle := certs.NewCertBundle()
	if config.CABundle == "" {
		cabundle.LoadDefaultBundle()
		cabundle.ImportBytes(papertrail.BundleCert())
	} else {
		cabundle.ImportFromFile(config.CABundle)
	}

	log.Printf("Connecting to %s over %s", destination, config.Destination.Protocol)
	logger, err := syslog.Dial(config.Destination.Protocol, destination, hostname, &cabundle)

	if err != nil {
		log.Fatalf("Cannot connect to server: %v", err)
	}

	for _, file := range config.Files {
		log.Printf("Forwarding %s", file)
		go tailFile(file, logger)
	}

	ch := make(chan bool)
	<-ch
}
<commit_msg>Add the ability to specify a hostname in the config file.<commit_after>package main

import (
	"encoding/json"
	"errors"
	"flag"
	"fmt"
	"github.com/ActiveState/tail"
	"github.com/sevenscale/remote_syslog2/papertrail"
	"github.com/sevenscale/remote_syslog2/syslog"
	"github.com/sevenscale/remote_syslog2/syslog/certs"
	"io/ioutil"
	"log"
	"os"
	"path"
	"time"
)

func tailFile(file string, logger *syslog.Conn) error {
	tailConfig := tail.Config{ReOpen: true, Follow: true, MustExist: false, Location: &tail.SeekInfo{0, os.SEEK_END}}
	t, err := tail.TailFile(file, tailConfig)

	if err != nil {
		log.Println(err)
		return err
	}

	for line := range t.Lines {
		p := syslog.Packet{
			Severity: syslog.SevInfo,
			Facility: syslog.LogLocal1, // todo: customize this
			Time:     time.Now(),
			Hostname: logger.Hostname(),
			Tag:      path.Base(file),
			Message:  line.Text,
		}
		err = logger.WritePacket(p)
		if err != nil {
			return err
		}

	}

	return errors.New("Tail worker executed abnormally")
}

type ConfigFile struct {
	Files       []string
	Destination struct {
		Host     string
		Port     int
		Protocol string
	}
	Hostname string
	CABundle string `json:"ca_bundle"`
}

func main() {
	configFile := flag.String("config", "/etc/remote_syslog2/config.json", "the configuration file")
	flag.Parse()

	log.Printf("Reading configuration file %s", *configFile)
	file, err := ioutil.ReadFile(*configFile)
	if err != nil {
		fmt.Println(err)
		os.Exit(1)
	}

	var config ConfigFile
	err = json.Unmarshal(file, &config)
	if err != nil {
		fmt.Println("The configfile is invalid: ", err)
		os.Exit(1)
	}

	var hostname string
	if config.Hostname == "" {
		// ignore error, we'll use the local addr when we connect
		hostname, _ = os.Hostname()
	} else {
		hostname = config.Hostname
	}

	destination := fmt.Sprintf("%s:%d", config.Destination.Host, config.Destination.Port)
	cabundle := certs.NewCertBundle()
	if config.CABundle == "" {
		cabundle.LoadDefaultBundle()
		cabundle.ImportBytes(papertrail.BundleCert())
	} else {
		cabundle.ImportFromFile(config.CABundle)
	}

	log.Printf("Connecting to %s over %s", destination, config.Destination.Protocol)
	logger, err := syslog.Dial(config.Destination.Protocol, destination, hostname, &cabundle)

	if err != nil {
		log.Fatalf("Cannot connect to server: %v", err)
	}

	for _, file := range config.Files {
		log.Printf("Forwarding %s", file)
		go tailFile(file, logger)
	}

	ch := make(chan bool)
	<-ch
}
<|endoftext|>


<commit_before>package main

import (
  "encoding/json"
  "flag"
  "fmt"
  "os"
  "io/ioutil"
  "net/http"
	"github.com/fractalcat/nagiosplugin"
)

var condition *string
var stream    *string
var url       *string
var user      *string
var pass      *string

func init() {
  condition = flag.String("condition", "<ID>", "Condition ID, set only to check a single alert (optional)")
  stream    = flag.String("stream",    "<ID>", "Stream ID (mandatory)")
  url       = flag.String("url",       "http://localhost:12900", "URL to Graylog2 api (optional)")
  user      = flag.String("user",      "<username>", "API username (mandatory)")
  pass      = flag.String("password",  "<password>", "API password (mandatory)")
}

func main() {
  flag.Parse()
  checkArguments()

  check := nagiosplugin.NewCheck()
  defer check.Finish()

  var data map[string]interface{}
  queryApi(*url + "/streams/" + *stream + "/alerts/check", *user, *pass, &data)

  total   := data["total_triggered"].(float64)
  results := data["results"].([]interface{})

  var stream_title string
  queryApi(*url + "/streams/" + *stream, *user, *pass, &data)
  stream_title = data["title"].(string)

  for i, result := range results {
    i = i
    mappedResult    := result.(map[string]interface{})
    mappedCondition := mappedResult["condition"].(map[string]interface{})
    if *condition != "<ID>" && *condition == mappedCondition["id"] && mappedResult["triggered"] == true {
      nagiosplugin.Exit(nagiosplugin.CRITICAL, "Alert triggered for stream '" + stream_title + "' condition: " + *condition)
    }
  }

  if total > 0  && *condition == "<ID>"{
    nagiosplugin.Exit(nagiosplugin.CRITICAL, fmt.Sprintf("%g", total) + " alert/s triggered for stream " + stream_title)
  }

  check.AddResult(nagiosplugin.OK, "No stream alerts triggered for stream: " + stream_title)
}

func checkArguments() {
  if *stream == "<ID>" {
    fmt.Println("usage:")
    flag.PrintDefaults()
    os.Exit(1)
  }
}

func queryApi(url string, user string, pass string, data *map[string]interface{}) {
  client := &http.Client{}
  req, err := http.NewRequest("GET", url, nil)
  req.SetBasicAuth(user, pass)
  res, err := client.Do(req)
  if err != nil {
    nagiosplugin.Exit(nagiosplugin.UNKNOWN, "Can not connect to Graylog2 API")
  }
  defer res.Body.Close()

  body, err := ioutil.ReadAll(res.Body)
  if err != nil {
    nagiosplugin.Exit(nagiosplugin.UNKNOWN, "Got no response from Graylog2 API")
  }

  err = json.Unmarshal(body, data)
  if err != nil {
    nagiosplugin.Exit(nagiosplugin.UNKNOWN, "Can not parse JSON from Graylog2 API")
  }
}
<commit_msg>catch wrong api return code<commit_after>package main

import (
  "encoding/json"
  "flag"
  "fmt"
  "os"
  "io/ioutil"
  "net/http"
	"github.com/fractalcat/nagiosplugin"
)

var condition *string
var stream    *string
var url       *string
var user      *string
var pass      *string

func init() {
  condition = flag.String("condition", "<ID>", "Condition ID, set only to check a single alert (optional)")
  stream    = flag.String("stream",    "<ID>", "Stream ID (mandatory)")
  url       = flag.String("url",       "http://localhost:12900", "URL to Graylog2 api (optional)")
  user      = flag.String("user",      "<username>", "API username (mandatory)")
  pass      = flag.String("password",  "<password>", "API password (mandatory)")
}

func main() {
  flag.Parse()
  checkArguments()

  check := nagiosplugin.NewCheck()
  defer check.Finish()

  var data map[string]interface{}
  queryApi(*url + "/streams/" + *stream + "/alerts/check", *user, *pass, &data)

  total   := data["total_triggered"].(float64)
  results := data["results"].([]interface{})

  var stream_title string
  queryApi(*url + "/streams/" + *stream, *user, *pass, &data)
  stream_title = data["title"].(string)

  for i, result := range results {
    i = i
    mappedResult    := result.(map[string]interface{})
    mappedCondition := mappedResult["condition"].(map[string]interface{})
    if *condition != "<ID>" && *condition == mappedCondition["id"] && mappedResult["triggered"] == true {
      nagiosplugin.Exit(nagiosplugin.CRITICAL, "Alert triggered for stream '" + stream_title + "' condition: " + *condition)
    }
  }

  if total > 0  && *condition == "<ID>"{
    nagiosplugin.Exit(nagiosplugin.CRITICAL, fmt.Sprintf("%g", total) + " alert/s triggered for stream " + stream_title)
  }

  check.AddResult(nagiosplugin.OK, "No stream alerts triggered for stream: " + stream_title)
}

func checkArguments() {
  if *stream == "<ID>" {
    fmt.Println("usage:")
    flag.PrintDefaults()
    os.Exit(1)
  }
}

func queryApi(url string, user string, pass string, data *map[string]interface{}) {
  client := &http.Client{}
  req, err := http.NewRequest("GET", url, nil)
  req.SetBasicAuth(user, pass)
  res, err := client.Do(req)
  if err != nil {
    nagiosplugin.Exit(nagiosplugin.UNKNOWN, "Can not connect to Graylog2 API")
  }
  defer res.Body.Close()

  body, err := ioutil.ReadAll(res.Body)
  if err != nil {
    nagiosplugin.Exit(nagiosplugin.UNKNOWN, "Got no response from Graylog2 API")
  }

  err = json.Unmarshal(body, data)
  if err != nil {
    nagiosplugin.Exit(nagiosplugin.UNKNOWN, "Can not parse JSON from Graylog2 API")
  }

  if res.StatusCode != 200 {
    nagiosplugin.Exit(nagiosplugin.UNKNOWN, "Got wrong return code from Graylog2 API, please check all command line parameters")
  }
}
<|endoftext|>


<commit_before>package publish

import (
	"fmt"

	"github.com/jinzhu/gorm"
)

func SetTableAndPublishStatus(force bool) func(*gorm.Scope) {
	return func(scope *gorm.Scope) {
		if draftMode, ok := scope.Get("qor_publish:draft_mode"); force || ok {
			if isDraft, ok := draftMode.(bool); force || ok && isDraft {
				currentModel := modelType(scope.IndirectValue().Interface()).String()

				var supportedModels []string
				if value, ok := scope.Get("publish:support_models"); ok {
					supportedModels = value.([]string)
				}

				for _, model := range supportedModels {
					if model == currentModel {
						table := scope.TableName()
						scope.InstanceSet("publish:original_table", table)
						scope.InstanceSet("publish:supported_model", true)
						scope.Search.TableName = DraftTableName(table)
						if isDraft {
							scope.SetColumn("PublishStatus", DIRTY)
						}
						break
					}
				}
			}
		}
	}
}

func GetModeAndNewScope(scope *gorm.Scope) (isProduction bool, clone *gorm.Scope) {
	if draftMode, ok := scope.Get("qor_publish:draft_mode"); ok && !draftMode.(bool) {
		if table, ok := scope.InstanceGet("publish:original_table"); ok {
			clone := scope.New(scope.Value)
			clone.Search.TableName = table.(string)
			return true, clone
		}
	}
	return false, nil
}

func SyncToProductionAfterCreate(scope *gorm.Scope) {
	if ok, clone := GetModeAndNewScope(scope); ok {
		gorm.Create(clone)
	}
}

func SyncToProductionAfterUpdate(scope *gorm.Scope) {
	if ok, clone := GetModeAndNewScope(scope); ok {
		gorm.Update(clone)
	}
}

func SyncToProductionAfterDelete(scope *gorm.Scope) {
	if ok, clone := GetModeAndNewScope(scope); ok {
		gorm.Delete(clone)
	}
}

func Delete(scope *gorm.Scope) {
	if !scope.HasError() {
		_, supportedModel := scope.InstanceGet("publish:supported_model")
		isDraftMode, ok := scope.Get("qor_publish:draft_mode")

		if supportedModel && (ok && isDraftMode.(bool)) {
			scope.Raw(
				fmt.Sprintf("UPDATE %v SET deleted_at=%v, publish_status=%v %v",
					scope.QuotedTableName(),
					scope.AddToVars(gorm.NowFunc()),
					scope.AddToVars(DIRTY),
					scope.CombinedConditionSql(),
				))
			scope.Exec()
		} else {
			gorm.Delete(scope)
		}
	}
}
<commit_msg>update publish callbacks with new gorm API<commit_after>package publish

import (
	"fmt"

	"github.com/jinzhu/gorm"
)

func SetTableAndPublishStatus(force bool) func(*gorm.Scope) {
	return func(scope *gorm.Scope) {
		if draftMode, ok := scope.Get("qor_publish:draft_mode"); force || ok {
			if isDraft, ok := draftMode.(bool); force || ok && isDraft {
				currentModel := modelType(scope.IndirectValue().Interface()).String()

				var supportedModels []string
				if value, ok := scope.Get("publish:support_models"); ok {
					supportedModels = value.([]string)
				}

				for _, model := range supportedModels {
					if model == currentModel {
						table := scope.TableName()
						scope.InstanceSet("publish:original_table", table)
						scope.InstanceSet("publish:supported_model", true)
						scope.Search.Table(DraftTableName(table))
						if isDraft {
							scope.SetColumn("PublishStatus", DIRTY)
						}
						break
					}
				}
			}
		}
	}
}

func GetModeAndNewScope(scope *gorm.Scope) (isProduction bool, clone *gorm.Scope) {
	if draftMode, ok := scope.Get("qor_publish:draft_mode"); ok && !draftMode.(bool) {
		if table, ok := scope.InstanceGet("publish:original_table"); ok {
			clone := scope.New(scope.Value)
			scope.Search.Table(table.(string))
			return true, clone
		}
	}
	return false, nil
}

func SyncToProductionAfterCreate(scope *gorm.Scope) {
	if ok, clone := GetModeAndNewScope(scope); ok {
		gorm.Create(clone)
	}
}

func SyncToProductionAfterUpdate(scope *gorm.Scope) {
	if ok, clone := GetModeAndNewScope(scope); ok {
		gorm.Update(clone)
	}
}

func SyncToProductionAfterDelete(scope *gorm.Scope) {
	if ok, clone := GetModeAndNewScope(scope); ok {
		gorm.Delete(clone)
	}
}

func Delete(scope *gorm.Scope) {
	if !scope.HasError() {
		_, supportedModel := scope.InstanceGet("publish:supported_model")
		isDraftMode, ok := scope.Get("qor_publish:draft_mode")

		if supportedModel && (ok && isDraftMode.(bool)) {
			scope.Raw(
				fmt.Sprintf("UPDATE %v SET deleted_at=%v, publish_status=%v %v",
					scope.QuotedTableName(),
					scope.AddToVars(gorm.NowFunc()),
					scope.AddToVars(DIRTY),
					scope.CombinedConditionSql(),
				))
			scope.Exec()
		} else {
			gorm.Delete(scope)
		}
	}
}
<|endoftext|>


<commit_before>package httpcheck

import (
	"code.google.com/p/go.net/publicsuffix"
	"log"
	"net/http"
	"net/http/cookiejar"
)

type Tester interface {
	Test() error
}

var RequestTimeout uint = 5  // Timeout for each HTTP request (seconds)
var ServerTimeout uint = 120 // Timeout for a server's tests (seconds)
var Verbose = false          // If true, every request is printed to standard output

var client http.Client
var version = "httpcheck/2.0"

// Set up a HTTP client with a cookie jar
func init() {
	options := cookiejar.Options{
		PublicSuffixList: publicsuffix.List,
	}

	jar, err := cookiejar.New(&options)
	if err != nil {
		log.Fatal(err)
	}

	client = http.Client{
		Jar: jar,
		CheckRedirect: func(req *http.Request, via []*http.Request) error {
			req.Header.Add("User-Agent", version)
			return nil
		},
	}
}
<commit_msg>httpcheck: bump version to 2.1<commit_after>package httpcheck

import (
	"code.google.com/p/go.net/publicsuffix"
	"log"
	"net/http"
	"net/http/cookiejar"
)

type Tester interface {
	Test() error
}

var RequestTimeout uint = 5  // Timeout for each HTTP request (seconds)
var ServerTimeout uint = 120 // Timeout for a server's tests (seconds)
var Verbose = false          // If true, every request is printed to standard output

var client http.Client
var version = "httpcheck/2.1"

// Set up a HTTP client with a cookie jar
func init() {
	options := cookiejar.Options{
		PublicSuffixList: publicsuffix.List,
	}

	jar, err := cookiejar.New(&options)
	if err != nil {
		log.Fatal(err)
	}

	client = http.Client{
		Jar: jar,
		CheckRedirect: func(req *http.Request, via []*http.Request) error {
			req.Header.Add("User-Agent", version)
			return nil
		},
	}
}
<|endoftext|>


<commit_before>package proxyclient

import (
	"testing"
	"bytes"
	"io"
	"net"
	"fmt"
)

const (CONNECT = "CONNECT")

// 伪装成为一个代理服务器。
func testHTTPProixyServer(t *testing.T, proxyAddr string, rAddr string, ci chan int) {

	l, err := net.Listen("tcp", proxyAddr)
	if err != nil {
		t.Fatalf("监听错误:%v", err)
	}

	ci <- 1
	c, err := l.Accept()
	if err != nil {
		t.Fatalf("接受连接错误:%v", err)
	}

	b := make([]byte, 1024)

	if _, err := c.Read(b); err != nil {
		t.Fatalf("读错误：%v", err)
	}/*else {
		b = b[:n]
		t.Log(string(b))
	}*/

	connect := CONNECT + " " + rAddr

	if bytes.Equal(b[:len(connect)], []byte(connect)) != true {
		t.Fatalf("命令不匹配！")
	}

	if bytes.Index(b, []byte("User-Agent")) < 0 {
		t.Fatalf("请求中未发现 User-Agent")
	}

	if _, err := c.Write([]byte("HTTP/1.0 200 ok\r\nAAA:111\r\n\r\n")); err != nil {
		t.Fatalf("写数据错误")
	}

	if _, err := c.Read(b[:1024]); err != nil {
		t.Fatalf("读错误：%v", err)
	}/*else {
		b = b[:n]
		print(b)
	}*/

	if _, err := c.Write([]byte("HTTP/1.0 200 ok\r\nHead1:11111\r\n\r\nHello Word!")); err != nil {
		t.Fatalf("写数据错误")
	}

	c.Close()

}

func TestHttpProxy(t *testing.T) {
	ci := make(chan int)
	go testHTTPProixyServer(t, "127.0.0.1:1331", "www.google.com:80", ci)
	<-ci

	p, err := NewProxyClient("http://127.0.0.1:1331?standardheader=True")
	if err != nil {
		t.Fatalf("连接代理服务器错误：%v", err)
	}

	c, err := p.Dial("tcp", "www.google.com:80")
	if err != nil {
		t.Fatalf("通过代理服务器连接目标网站失败：%v", err)
	}

	if _, err := c.Write([]byte("GET / HTTP/1.0\r\nHOST:www.google.com\r\n\r\n")); err != nil {
		t.Fatalf("请求发送错误：%v", err)
	}

	b := make([]byte, 1024)
	if n, err := c.Read(b); err != nil {
		t.Fatalf("响应读取错误：%v", err)
	}else {
		b = b[:n]
	}

	if bytes.Equal(b, []byte("HTTP/1.0 200 ok\r\nHead1:11111\r\n\r\nHello Word!")) != true {
		t.Fatalf("返回内容不匹配：%v", string(b))
	}

	if _, err := c.Read(b[:1024]); err != io.EOF {
		t.Fatalf("非预期的结尾：%v", err)
	}

}

<commit_msg>imported and not used: "fmt"<commit_after>package proxyclient

import (
	"testing"
	"bytes"
	"io"
	"net"
)

const (CONNECT = "CONNECT")

// 伪装成为一个代理服务器。
func testHTTPProixyServer(t *testing.T, proxyAddr string, rAddr string, ci chan int) {

	l, err := net.Listen("tcp", proxyAddr)
	if err != nil {
		t.Fatalf("监听错误:%v", err)
	}

	ci <- 1
	c, err := l.Accept()
	if err != nil {
		t.Fatalf("接受连接错误:%v", err)
	}

	b := make([]byte, 1024)

	if _, err := c.Read(b); err != nil {
		t.Fatalf("读错误：%v", err)
	}/*else {
		b = b[:n]
		t.Log(string(b))
	}*/

	connect := CONNECT + " " + rAddr

	if bytes.Equal(b[:len(connect)], []byte(connect)) != true {
		t.Fatalf("命令不匹配！")
	}

	if bytes.Index(b, []byte("User-Agent")) < 0 {
		t.Fatalf("请求中未发现 User-Agent")
	}

	if _, err := c.Write([]byte("HTTP/1.0 200 ok\r\nAAA:111\r\n\r\n")); err != nil {
		t.Fatalf("写数据错误")
	}

	if _, err := c.Read(b[:1024]); err != nil {
		t.Fatalf("读错误：%v", err)
	}/*else {
		b = b[:n]
		print(b)
	}*/

	if _, err := c.Write([]byte("HTTP/1.0 200 ok\r\nHead1:11111\r\n\r\nHello Word!")); err != nil {
		t.Fatalf("写数据错误")
	}

	c.Close()

}

func TestHttpProxy(t *testing.T) {
	ci := make(chan int)
	go testHTTPProixyServer(t, "127.0.0.1:1331", "www.google.com:80", ci)
	<-ci

	p, err := NewProxyClient("http://127.0.0.1:1331?standardheader=True")
	if err != nil {
		t.Fatalf("连接代理服务器错误：%v", err)
	}

	c, err := p.Dial("tcp", "www.google.com:80")
	if err != nil {
		t.Fatalf("通过代理服务器连接目标网站失败：%v", err)
	}

	if _, err := c.Write([]byte("GET / HTTP/1.0\r\nHOST:www.google.com\r\n\r\n")); err != nil {
		t.Fatalf("请求发送错误：%v", err)
	}

	b := make([]byte, 1024)
	if n, err := c.Read(b); err != nil {
		t.Fatalf("响应读取错误：%v", err)
	}else {
		b = b[:n]
	}

	if bytes.Equal(b, []byte("HTTP/1.0 200 ok\r\nHead1:11111\r\n\r\nHello Word!")) != true {
		t.Fatalf("返回内容不匹配：%v", string(b))
	}

	if _, err := c.Read(b[:1024]); err != io.EOF {
		t.Fatalf("非预期的结尾：%v", err)
	}

}

<|endoftext|>


<commit_before>// Copyright (c) 2016, Janoš Guljaš <janos@resenje.org>
// All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package httputils

import (
	"crypto/tls"
	"io"
	"net"
	"net/http"
	"time"
)

type conn struct {
	net.Conn
	b byte
	e error
	f bool
}

func (c *conn) Read(b []byte) (int, error) {
	if c.f {
		c.f = false
		b[0] = c.b
		if len(b) > 1 && c.e == nil {
			n, e := c.Conn.Read(b[1:])
			if e != nil {
				c.Conn.Close()
			}
			return n + 1, e
		}
		return 1, c.e
	}
	return c.Conn.Read(b)
}

// TLSListener is a TCP listener that will check if the connection should be
// encrypted, and return encrypted connection, and if not, to return plain
// connection. It can be used along with HTTPToHTTPSRedirectHandler, to
// automatically redirect users from http:// to https:// protocol, by checking
// if http.Request has TLS equal to nil. Or to provide provide a different
// content in case that client provided or not TLS connection.
type TLSListener struct {
	*net.TCPListener
	TLSConfig *tls.Config
}

// Accept accepts TCP connection, sets keep alive and checks if a client
// requested an encrypted connection.
func (l TLSListener) Accept() (net.Conn, error) {
	c, err := l.AcceptTCP()
	if err != nil {
		return nil, err
	}
	c.SetKeepAlive(true)
	c.SetKeepAlivePeriod(3 * time.Minute)

	b := make([]byte, 1)
	_, err = c.Read(b)
	if err != nil {
		c.Close()
		if err != io.EOF {
			return nil, err
		}
	}

	con := &conn{
		Conn: c,
		b:    b[0],
		e:    err,
		f:    true,
	}

	if b[0] == 22 {
		return tls.Server(con, l.TLSConfig), nil
	}

	return con, nil
}

// HTTPToHTTPSRedirectHandler redirects with status code 301 to a https://
// version of HTTP request.
func HTTPToHTTPSRedirectHandler(w http.ResponseWriter, r *http.Request) {
	w.Header().Set("Location", "https://"+r.Host+r.RequestURI)
	w.WriteHeader(http.StatusMovedPermanently)
}
<commit_msg>Fix HTTPToHTTPSRedirectHandler URL handling<commit_after>// Copyright (c) 2016, Janoš Guljaš <janos@resenje.org>
// All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package httputils

import (
	"crypto/tls"
	"io"
	"net"
	"net/http"
	"time"
)

type conn struct {
	net.Conn
	b byte
	e error
	f bool
}

func (c *conn) Read(b []byte) (int, error) {
	if c.f {
		c.f = false
		b[0] = c.b
		if len(b) > 1 && c.e == nil {
			n, e := c.Conn.Read(b[1:])
			if e != nil {
				c.Conn.Close()
			}
			return n + 1, e
		}
		return 1, c.e
	}
	return c.Conn.Read(b)
}

// TLSListener is a TCP listener that will check if the connection should be
// encrypted, and return encrypted connection, and if not, to return plain
// connection. It can be used along with HTTPToHTTPSRedirectHandler, to
// automatically redirect users from http:// to https:// protocol, by checking
// if http.Request has TLS equal to nil. Or to provide provide a different
// content in case that client provided or not TLS connection.
type TLSListener struct {
	*net.TCPListener
	TLSConfig *tls.Config
}

// Accept accepts TCP connection, sets keep alive and checks if a client
// requested an encrypted connection.
func (l TLSListener) Accept() (net.Conn, error) {
	c, err := l.AcceptTCP()
	if err != nil {
		return nil, err
	}
	c.SetKeepAlive(true)
	c.SetKeepAlivePeriod(3 * time.Minute)

	b := make([]byte, 1)
	_, err = c.Read(b)
	if err != nil {
		c.Close()
		if err != io.EOF {
			return nil, err
		}
	}

	con := &conn{
		Conn: c,
		b:    b[0],
		e:    err,
		f:    true,
	}

	if b[0] == 22 {
		return tls.Server(con, l.TLSConfig), nil
	}

	return con, nil
}

// HTTPToHTTPSRedirectHandler redirects with status code 301 to a https://
// version of HTTP request.
func HTTPToHTTPSRedirectHandler(w http.ResponseWriter, r *http.Request) {
	url := r.URL
	url.Scheme = "https"
	if url.Host == "" {
		url.Host = r.Host
	}
	w.Header().Set("Location", url.String())
	w.WriteHeader(http.StatusMovedPermanently)
}
<|endoftext|>


<commit_before>package homecloud

import (
	"encoding/json"
	"fmt"
	"regexp"
	"time"

	"git.eclipse.org/gitroot/paho/org.eclipse.paho.mqtt.golang.git"
	"github.com/ninjasphere/go-ninja/api"
	"github.com/ninjasphere/go-ninja/config"
	"github.com/ninjasphere/go-ninja/logger"
	"github.com/ninjasphere/go-ninja/model"
	"github.com/ninjasphere/go-ninja/rpc/json2"
	"github.com/ninjasphere/redigo/redis"
)

var log = logger.GetLogger("HomeCloud")

var conn *ninja.Connection

var thingModel *ThingModel
var deviceModel *DeviceModel
var channelModel *ChannelModel
var roomModel *RoomModel
var driverModel *DriverModel

var locationRegexp = regexp.MustCompile("\\$device\\/([A-F0-9]*)\\/[^\\/]*\\/location")

type incomingLocationUpdate struct {
	Zone *string `json:"zone,omitempty"`
}

type outgoingLocationUpdate struct {
	ID         *string `json:"id"`
	HasChanged bool    `json:"hasChanged"`
}

var RedisPool = &redis.Pool{
	MaxIdle:     3,
	IdleTimeout: 240 * time.Second,
	Dial: func() (redis.Conn, error) {
		c, err := redis.Dial("tcp", ":6379")
		if err != nil {
			return nil, err
		}
		/*if _, err := c.Do("AUTH", password); err != nil {
			c.Close()
			return nil, err
		}*/
		return c, err
	},
	TestOnBorrow: func(c redis.Conn, t time.Time) error {
		_, err := c.Do("PING")
		return err
	},
}

func Start(c *ninja.Connection) {

	//FIXME
	conn = c

	thingModel = NewThingModel(RedisPool, conn)
	conn.MustExportService(thingModel, "$home/services/ThingModel", &model.ServiceAnnouncement{
		Schema: "/service/thing-model",
	})

	deviceModel = NewDeviceModel(RedisPool, conn)
	conn.MustExportService(deviceModel, "$home/services/DeviceModel", &model.ServiceAnnouncement{
		Schema: "/service/device-model",
	})

	channelModel = NewChannelModel(RedisPool, conn)
	conn.MustExportService(deviceModel, "$home/services/ChannelModel", &model.ServiceAnnouncement{
		Schema: "/service/channel-model",
	})

	roomModel = NewRoomModel(RedisPool, conn)
	conn.MustExportService(roomModel, "$home/services/RoomModel", &model.ServiceAnnouncement{
		Schema: "/service/room-model",
	})

	if config.Bool(false, "clearcloud") {
		log.Infof("Clearing all cloud data in 5 seconds")

		time.Sleep(time.Second * 5)

		thingModel.ClearCloud()
		channelModel.ClearCloud()
		deviceModel.ClearCloud()
		roomModel.ClearCloud()

		log.Infof("All cloud data cleared? Probably.")

		return
	}

	go func() {
		for {
			log.Infof("\n\n\n------ Timed model syncing started (every 30 min) ------ ")

			roomResult := roomModel.sync()
			deviceResult := deviceModel.sync()
			channelResult := channelModel.sync()
			thingResult := thingModel.sync()

			log.Infof("Room sync error: %s", roomResult)
			log.Infof("Device sync error: %s", deviceResult)
			log.Infof("Channel sync error: %s", channelResult)
			log.Infof("Thing sync error: %s", thingResult)

			log.Infof("------ Timed model syncing complete ------\n\n\n")

			time.Sleep(time.Minute * 30)
		}
	}()

	driverModel = NewDriverModel(RedisPool, conn)

	startManagingDrivers()
	startManagingDevices()
	startMonitoringLocations()

	go func() {
		// Give it a chance to sync first...
		time.Sleep(time.Second * 10)
		startDrivers()
	}()

}

func startDrivers() {

	do := func(name string, task string) error {
		return conn.SendNotification("$node/"+config.Serial()+"/module/"+task, name)
	}

	for _, name := range []string{"driver-go-zigbee", "driver-go-sonos", "driver-go-lifx", "driver-go-ble", "driver-go-hue", "driver-go-wemo", "driver-go-flowerpower"} {
		log.Infof("-- (Re)starting '%s'", name)

		err := do(name, "stop")
		if err != nil {
			log.Fatalf("Failed to send %s stop message! %s", name, err)
		}

		time.Sleep(time.Second * 2)

		err = do(name, "start")
		if err != nil {
			log.Fatalf("Failed to send %s start message! %s", name, err)
		}
	}

}

func startDriver(node string, driverID string, config *string) error {

	var rawConfig json.RawMessage
	if config != nil {
		rawConfig = []byte(*config)
	} else {
		rawConfig = []byte("{}")
	}

	client := conn.GetServiceClient(fmt.Sprintf("$node/%s/driver/%s", node, driverID))
	err := client.Call("start", &rawConfig, nil, 10*time.Second)

	if err != nil {
		jsonError, ok := err.(*json2.Error)
		if ok {
			if jsonError.Code == json2.E_INVALID_REQ {

				err := driverModel.DeleteConfig(driverID)
				if err != nil {
					log.Warningf("Driver %s could not parse its config. Also, we couldn't clear it! errors:%s and %s", driverID, jsonError.Message, err)
				} else {
					log.Warningf("Driver %s could not parse its config, so we cleared it from redis. error:%s", driverID, jsonError.Message)
				}

				return startDriver(node, driverID, nil)
			}
		}
	}

	return err
}

func startManagingDrivers() {

	conn.Subscribe("$node/:node/driver/:driver/event/announce", func(announcement *json.RawMessage, values map[string]string) bool {

		node, driver := values["node"], values["driver"]

		log.Infof("Got driver announcement node:%s driver:%s", node, driver)

		if announcement == nil {
			log.Warningf("Nil driver announcement from node:%s driver:%s", node, driver)
			return true
		}

		module := &model.Module{}
		err := json.Unmarshal(*announcement, module)

		if announcement == nil {
			log.Warningf("Could not parse announcement from node:%s driver:%s error:%s", node, driver, err)
			return true
		}

		err = driverModel.Create(module)
		if err != nil {
			log.Warningf("Failed to save driver announcement for %s error:%s", driver, err)
		}

		config, err := driverModel.GetConfig(values["driver"])

		if err != nil {
			log.Warningf("Failed to retrieve config for driver %s error:%s", driver, err)
		} else {
			err = startDriver(node, driver, config)
			if err != nil {
				log.Warningf("Failed to start driver: %s error:%s", driver, err)
			}
		}

		return true
	})

	conn.Subscribe("$node/:node/driver/:driver/event/config", func(config *json.RawMessage, values map[string]string) bool {
		log.Infof("Got driver config node:%s driver:%s config:%s", values["node"], values["driver"], *config)

		if config != nil {
			err := driverModel.SetConfig(values["driver"], string(*config))

			if err != nil {
				log.Warningf("Failed to save config for driver: %s error: %s", values["driver"], err)
			}
		} else {
			log.Infof("Nil config recevied from node:%s driver:%s", values["node"], values["driver"])
		}

		return true
	})

}

func startManagingDevices() {

	conn.Subscribe("$device/:id/event/announce", func(announcement *json.RawMessage, values map[string]string) bool {

		id := values["id"]

		log.Infof("Got device announcement device:%s", id)

		if announcement == nil {
			log.Warningf("Nil driver announcement from device:%s", id)
			return true
		}

		device := &model.Device{}
		err := json.Unmarshal(*announcement, device)

		if announcement == nil {
			log.Warningf("Could not parse announcement from device:%s error:%s", id, err)
			return true
		}

		err = deviceModel.Create(device)
		if err != nil {
			log.Warningf("Failed to save device announcement for device:%s error:%s", id, err)
		}

		return true
	})

	conn.Subscribe("$device/:device/channel/:channel/event/announce", func(announcement *json.RawMessage, values map[string]string) bool {

		deviceID, channelID := values["device"], values["channel"]

		log.Infof("Got channel announcement device:%s channel:%s", deviceID, channelID)

		if announcement == nil {
			log.Warningf("Nil channel announcement from device:%s channel:%s", deviceID, channelID)
			return true
		}

		channel := &model.Channel{}
		err := json.Unmarshal(*announcement, channel)

		if announcement == nil {
			log.Warningf("Could not parse channel announcement from device:%s channel:%s error:%s", deviceID, channelID, err)
			return true
		}

		err = channelModel.Create(deviceID, channel)
		if err != nil {
			log.Warningf("Failed to save channel announcement for device:%s channel:%s error:%s", deviceID, channelID, err)
		}

		return true
	})

}

func startMonitoringLocations() {

	filter, err := mqtt.NewTopicFilter("$device/+/+/location", 0)
	if err != nil {
		log.FatalError(err, "Failed to subscribe to device locations")
	}

	receipt, err := conn.GetMqttClient().StartSubscription(func(_ *mqtt.MqttClient, message mqtt.Message) {

		deviceID := locationRegexp.FindAllStringSubmatch(message.Topic(), -1)[0][1]

		update := &incomingLocationUpdate{}
		err := json.Unmarshal(message.Payload(), update)
		if err != nil {
			log.Errorf("Failed to parse location update %s to %s : %s", message.Payload(), message.Topic(), err)
			return
		}

		thing, err := thingModel.FetchByDeviceId(deviceID)
		if err != nil {
			log.FatalError(err, fmt.Sprintf("Failed to fetch thing by device id %s", deviceID))
		}

		if update.Zone == nil {
			log.Debugf("< Incoming location update: device %s not in a zone", deviceID)
		} else {
			log.Debugf("< Incoming location update: device %s is in zone %s", deviceID, *update.Zone)
		}

		hasChangedZone := true

		if thing == nil {
			log.Debugf("Device %s is not attached to a thing. Ignoring.", deviceID)
		} else {

			if (thing.Location != nil && update.Zone != nil && *thing.Location == *update.Zone) || (thing.Location == nil && update.Zone == nil) {
				// It's already there
				log.Debugf("Thing %s (%s) (Device %s) was already in that zone.", thing.ID, thing.Name, deviceID)
				hasChangedZone = true
			} else {

				log.Debugf("Thing %s (%s) (Device %s) moved from %s to %s", thing.ID, thing.Name, deviceID, thing.Location, update.Zone)

				err = roomModel.MoveThing(thing.Location, update.Zone, thing.ID)

				if err != nil {
					log.FatalError(err, fmt.Sprintf("Failed to update location of thing %s", thing.ID))
				}

				err = thingModel.SetLocation(thing.ID, update.Zone)
				if err != nil {
					log.FatalError(err, fmt.Sprintf("Failed to update location property of thing %s", thing.ID))
				}

				if update.Zone != nil {
					room, err := roomModel.Fetch(*update.Zone)
					if err != nil {
						log.FatalError(err, fmt.Sprintf("Failed to fetch room %s", *update.Zone))
					}

					if room == nil {
						// XXX: TODO: Remove me once the cloud room model is sync'd and locatino service uses it
						log.Infof("Unknown room %s. Advising remote location service to forget it.", *update.Zone)

						pubReceipt := conn.GetMqttClient().Publish(mqtt.QoS(0), "$location/delete", message.Payload())
						<-pubReceipt
					}
				}
			}

			topic := fmt.Sprintf("$device/%s/channel/%s/%s/event/state", deviceID, "location", "location")

			payload, _ := json.Marshal(&outgoingLocationUpdate{
				ID:         update.Zone,
				HasChanged: hasChangedZone,
			})

			pubReceipt := conn.GetMqttClient().Publish(mqtt.QoS(0), topic, payload)
			<-pubReceipt

		}

	}, filter)

	if err != nil {
		log.Fatalf("Failed to subscribe to device locations: %s", err)
	}

	<-receipt
}
<commit_msg>Fix err check in channel announcement handling<commit_after>package homecloud

import (
	"encoding/json"
	"fmt"
	"regexp"
	"time"

	"git.eclipse.org/gitroot/paho/org.eclipse.paho.mqtt.golang.git"
	"github.com/ninjasphere/go-ninja/api"
	"github.com/ninjasphere/go-ninja/config"
	"github.com/ninjasphere/go-ninja/logger"
	"github.com/ninjasphere/go-ninja/model"
	"github.com/ninjasphere/go-ninja/rpc/json2"
	"github.com/ninjasphere/redigo/redis"
)

var log = logger.GetLogger("HomeCloud")

var conn *ninja.Connection

var thingModel *ThingModel
var deviceModel *DeviceModel
var channelModel *ChannelModel
var roomModel *RoomModel
var driverModel *DriverModel

var locationRegexp = regexp.MustCompile("\\$device\\/([A-F0-9]*)\\/[^\\/]*\\/location")

type incomingLocationUpdate struct {
	Zone *string `json:"zone,omitempty"`
}

type outgoingLocationUpdate struct {
	ID         *string `json:"id"`
	HasChanged bool    `json:"hasChanged"`
}

var RedisPool = &redis.Pool{
	MaxIdle:     3,
	IdleTimeout: 240 * time.Second,
	Dial: func() (redis.Conn, error) {
		c, err := redis.Dial("tcp", ":6379")
		if err != nil {
			return nil, err
		}
		/*if _, err := c.Do("AUTH", password); err != nil {
			c.Close()
			return nil, err
		}*/
		return c, err
	},
	TestOnBorrow: func(c redis.Conn, t time.Time) error {
		_, err := c.Do("PING")
		return err
	},
}

func Start(c *ninja.Connection) {

	//FIXME
	conn = c

	thingModel = NewThingModel(RedisPool, conn)
	conn.MustExportService(thingModel, "$home/services/ThingModel", &model.ServiceAnnouncement{
		Schema: "/service/thing-model",
	})

	deviceModel = NewDeviceModel(RedisPool, conn)
	conn.MustExportService(deviceModel, "$home/services/DeviceModel", &model.ServiceAnnouncement{
		Schema: "/service/device-model",
	})

	channelModel = NewChannelModel(RedisPool, conn)
	conn.MustExportService(deviceModel, "$home/services/ChannelModel", &model.ServiceAnnouncement{
		Schema: "/service/channel-model",
	})

	roomModel = NewRoomModel(RedisPool, conn)
	conn.MustExportService(roomModel, "$home/services/RoomModel", &model.ServiceAnnouncement{
		Schema: "/service/room-model",
	})

	if config.Bool(false, "clearcloud") {
		log.Infof("Clearing all cloud data in 5 seconds")

		time.Sleep(time.Second * 5)

		thingModel.ClearCloud()
		channelModel.ClearCloud()
		deviceModel.ClearCloud()
		roomModel.ClearCloud()

		log.Infof("All cloud data cleared? Probably.")

		return
	}

	go func() {
		for {
			log.Infof("\n\n\n------ Timed model syncing started (every 30 min) ------ ")

			roomResult := roomModel.sync()
			deviceResult := deviceModel.sync()
			channelResult := channelModel.sync()
			thingResult := thingModel.sync()

			log.Infof("Room sync error: %s", roomResult)
			log.Infof("Device sync error: %s", deviceResult)
			log.Infof("Channel sync error: %s", channelResult)
			log.Infof("Thing sync error: %s", thingResult)

			log.Infof("------ Timed model syncing complete ------\n\n\n")

			time.Sleep(time.Minute * 30)
		}
	}()

	driverModel = NewDriverModel(RedisPool, conn)

	startManagingDrivers()
	startManagingDevices()
	startMonitoringLocations()

	go func() {
		// Give it a chance to sync first...
		time.Sleep(time.Second * 10)
		startDrivers()
	}()

}

func startDrivers() {

	do := func(name string, task string) error {
		return conn.SendNotification("$node/"+config.Serial()+"/module/"+task, name)
	}

	for _, name := range []string{"driver-go-zigbee", "driver-go-sonos", "driver-go-lifx", "driver-go-ble", "driver-go-hue", "driver-go-wemo", "driver-go-flowerpower"} {
		log.Infof("-- (Re)starting '%s'", name)

		err := do(name, "stop")
		if err != nil {
			log.Fatalf("Failed to send %s stop message! %s", name, err)
		}

		time.Sleep(time.Second * 2)

		err = do(name, "start")
		if err != nil {
			log.Fatalf("Failed to send %s start message! %s", name, err)
		}
	}

}

func startDriver(node string, driverID string, config *string) error {

	var rawConfig json.RawMessage
	if config != nil {
		rawConfig = []byte(*config)
	} else {
		rawConfig = []byte("{}")
	}

	client := conn.GetServiceClient(fmt.Sprintf("$node/%s/driver/%s", node, driverID))
	err := client.Call("start", &rawConfig, nil, 10*time.Second)

	if err != nil {
		jsonError, ok := err.(*json2.Error)
		if ok {
			if jsonError.Code == json2.E_INVALID_REQ {

				err := driverModel.DeleteConfig(driverID)
				if err != nil {
					log.Warningf("Driver %s could not parse its config. Also, we couldn't clear it! errors:%s and %s", driverID, jsonError.Message, err)
				} else {
					log.Warningf("Driver %s could not parse its config, so we cleared it from redis. error:%s", driverID, jsonError.Message)
				}

				return startDriver(node, driverID, nil)
			}
		}
	}

	return err
}

func startManagingDrivers() {

	conn.Subscribe("$node/:node/driver/:driver/event/announce", func(announcement *json.RawMessage, values map[string]string) bool {

		node, driver := values["node"], values["driver"]

		log.Infof("Got driver announcement node:%s driver:%s", node, driver)

		if announcement == nil {
			log.Warningf("Nil driver announcement from node:%s driver:%s", node, driver)
			return true
		}

		module := &model.Module{}
		err := json.Unmarshal(*announcement, module)

		if announcement == nil {
			log.Warningf("Could not parse announcement from node:%s driver:%s error:%s", node, driver, err)
			return true
		}

		err = driverModel.Create(module)
		if err != nil {
			log.Warningf("Failed to save driver announcement for %s error:%s", driver, err)
		}

		config, err := driverModel.GetConfig(values["driver"])

		if err != nil {
			log.Warningf("Failed to retrieve config for driver %s error:%s", driver, err)
		} else {
			err = startDriver(node, driver, config)
			if err != nil {
				log.Warningf("Failed to start driver: %s error:%s", driver, err)
			}
		}

		return true
	})

	conn.Subscribe("$node/:node/driver/:driver/event/config", func(config *json.RawMessage, values map[string]string) bool {
		log.Infof("Got driver config node:%s driver:%s config:%s", values["node"], values["driver"], *config)

		if config != nil {
			err := driverModel.SetConfig(values["driver"], string(*config))

			if err != nil {
				log.Warningf("Failed to save config for driver: %s error: %s", values["driver"], err)
			}
		} else {
			log.Infof("Nil config recevied from node:%s driver:%s", values["node"], values["driver"])
		}

		return true
	})

}

func startManagingDevices() {

	conn.Subscribe("$device/:id/event/announce", func(announcement *json.RawMessage, values map[string]string) bool {

		id := values["id"]

		log.Infof("Got device announcement device:%s", id)

		if announcement == nil {
			log.Warningf("Nil driver announcement from device:%s", id)
			return true
		}

		device := &model.Device{}
		err := json.Unmarshal(*announcement, device)

		if announcement == nil {
			log.Warningf("Could not parse announcement from device:%s error:%s", id, err)
			return true
		}

		err = deviceModel.Create(device)
		if err != nil {
			log.Warningf("Failed to save device announcement for device:%s error:%s", id, err)
		}

		return true
	})

	conn.Subscribe("$device/:device/channel/:channel/event/announce", func(announcement *json.RawMessage, values map[string]string) bool {

		deviceID, channelID := values["device"], values["channel"]

		log.Infof("Got channel announcement device:%s channel:%s", deviceID, channelID)

		if announcement == nil {
			log.Warningf("Nil channel announcement from device:%s channel:%s", deviceID, channelID)
			return true
		}

		channel := &model.Channel{}
		err := json.Unmarshal(*announcement, channel)

		if err != nil {
			log.Warningf("Could not parse channel announcement from device:%s channel:%s error:%s", deviceID, channelID, err)
			return true
		}

		err = channelModel.Create(deviceID, channel)
		if err != nil {
			log.Warningf("Failed to save channel announcement for device:%s channel:%s error:%s", deviceID, channelID, err)
		}

		return true
	})

}

func startMonitoringLocations() {

	filter, err := mqtt.NewTopicFilter("$device/+/+/location", 0)
	if err != nil {
		log.FatalError(err, "Failed to subscribe to device locations")
	}

	receipt, err := conn.GetMqttClient().StartSubscription(func(_ *mqtt.MqttClient, message mqtt.Message) {

		deviceID := locationRegexp.FindAllStringSubmatch(message.Topic(), -1)[0][1]

		update := &incomingLocationUpdate{}
		err := json.Unmarshal(message.Payload(), update)
		if err != nil {
			log.Errorf("Failed to parse location update %s to %s : %s", message.Payload(), message.Topic(), err)
			return
		}

		thing, err := thingModel.FetchByDeviceId(deviceID)
		if err != nil {
			log.FatalError(err, fmt.Sprintf("Failed to fetch thing by device id %s", deviceID))
		}

		if update.Zone == nil {
			log.Debugf("< Incoming location update: device %s not in a zone", deviceID)
		} else {
			log.Debugf("< Incoming location update: device %s is in zone %s", deviceID, *update.Zone)
		}

		hasChangedZone := true

		if thing == nil {
			log.Debugf("Device %s is not attached to a thing. Ignoring.", deviceID)
		} else {

			if (thing.Location != nil && update.Zone != nil && *thing.Location == *update.Zone) || (thing.Location == nil && update.Zone == nil) {
				// It's already there
				log.Debugf("Thing %s (%s) (Device %s) was already in that zone.", thing.ID, thing.Name, deviceID)
				hasChangedZone = true
			} else {

				log.Debugf("Thing %s (%s) (Device %s) moved from %s to %s", thing.ID, thing.Name, deviceID, thing.Location, update.Zone)

				err = roomModel.MoveThing(thing.Location, update.Zone, thing.ID)

				if err != nil {
					log.FatalError(err, fmt.Sprintf("Failed to update location of thing %s", thing.ID))
				}

				err = thingModel.SetLocation(thing.ID, update.Zone)
				if err != nil {
					log.FatalError(err, fmt.Sprintf("Failed to update location property of thing %s", thing.ID))
				}

				if update.Zone != nil {
					room, err := roomModel.Fetch(*update.Zone)
					if err != nil {
						log.FatalError(err, fmt.Sprintf("Failed to fetch room %s", *update.Zone))
					}

					if room == nil {
						// XXX: TODO: Remove me once the cloud room model is sync'd and locatino service uses it
						log.Infof("Unknown room %s. Advising remote location service to forget it.", *update.Zone)

						pubReceipt := conn.GetMqttClient().Publish(mqtt.QoS(0), "$location/delete", message.Payload())
						<-pubReceipt
					}
				}
			}

			topic := fmt.Sprintf("$device/%s/channel/%s/%s/event/state", deviceID, "location", "location")

			payload, _ := json.Marshal(&outgoingLocationUpdate{
				ID:         update.Zone,
				HasChanged: hasChangedZone,
			})

			pubReceipt := conn.GetMqttClient().Publish(mqtt.QoS(0), topic, payload)
			<-pubReceipt

		}

	}, filter)

	if err != nil {
		log.Fatalf("Failed to subscribe to device locations: %s", err)
	}

	<-receipt
}
<|endoftext|>


<commit_before>package keybd_event

/*
 #cgo CFLAGS: -x objective-c
 #cgo LDFLAGS: -framework Cocoa
 #import <Foundation/Foundation.h>
 CGEventRef CreateDown(int k){
	CGEventRef event = CGEventCreateKeyboardEvent (NULL, (CGKeyCode)k, true);
	return event;
 }
 CGEventRef CreateUp(int k){
	CGEventRef event = CGEventCreateKeyboardEvent (NULL, (CGKeyCode)k, false);
	return event;
 }
 void KeyTap(CGEventRef event){
	CGEventPost(kCGAnnotatedSessionEventTap, event);
	CFRelease(event);
 }
 void AddActionKey(CGEventFlags type,CGEventRef event){
 	CGEventSetFlags(event, type);
 }
*/
import "C"
import "time"

const (
	_AShift          = C.kCGEventFlagMaskAlphaShift
	_VK_SHIFT        = C.kCGEventFlagMaskShift
	_VK_CTRL         = C.kCGEventFlagMaskControl
	_VK_ALT          = C.kCGEventFlagMaskAlternate
	_VK_CMD          = C.kCGEventFlagMaskCommand
	_Help            = C.kCGEventFlagMaskHelp
	_VK_FN           = C.kCGEventFlagMaskSecondaryFn
	_NumPad          = C.kCGEventFlagMaskNumericPad
	_Coalesced       = C.kCGEventFlagMaskNonCoalesced
	_VK_Control      = 0x3B
	_VK_RightShift   = 0x3C
	_VK_RightControl = 0x3E
	_VK_Command      = 0x37
	_VK_Shift        = 0x38
)

func initKeyBD() error { return nil }

// Press key(s)
func (k *KeyBonding) Press() error {
	for _, key := range k.keys {
		k.keyPress(key)
	}
	return nil
}

// Release key(s)
func (k *KeyBonding) Release() error {
	for _, key := range k.keys {
		k.keyRelease(key)
	}
	return nil
}

// Launch key bounding
func (k *KeyBonding) Launching() error {

	for _, key := range k.keys {
		k.tapKey(key)
	}
	return nil
}
func altgr(event C.CGEventRef) {
	alt(event)
}
func shift(event C.CGEventRef) {
	C.AddActionKey(_VK_SHIFT, event)
}
func ctrl(event C.CGEventRef) {
	C.AddActionKey(_VK_CTRL, event)
}
func alt(event C.CGEventRef) {
	C.AddActionKey(_VK_ALT, event)
}
func cmd(event C.CGEventRef) {
	C.AddActionKey(_VK_CMD, event)
}
func (k KeyBonding) keyPress(key int) {
	downEvent := C.CreateDown(C.int(key))
	if k.hasALT {
		alt(downEvent)
	}
	if k.hasCTRL {
		ctrl(downEvent)
	}
	if k.hasSHIFT {
		shift(downEvent)
	}
	if k.hasRCTRL { //not support on mac
		ctrl(downEvent)
	}
	if k.hasRSHIFT { //not support on mac
		shift(downEvent)
	}
	if k.hasALTGR {
		altgr(downEvent)
	}
	if k.hasSuper {
		cmd(downEvent)
	}
	C.KeyTap(downEvent)
}
func (k KeyBonding) keyRelease(key int) {
	upEvent := C.CreateUp(C.int(key))
	if k.hasALT {
		alt(upEvent)
	}
	if k.hasCTRL {
		ctrl(upEvent)
	}
	if k.hasSHIFT {
		shift(upEvent)
	}
	if k.hasRCTRL { //not support on mac
		ctrl(upEvent)
	}
	if k.hasRSHIFT { //not support on mac
		shift(upEvent)
	}
	if k.hasALTGR {
		altgr(upEvent)
	}
	if k.hasSuper {
		cmd(upEvent)
	}
	C.KeyTap(upEvent)
}
func (k KeyBonding) tapKey(key int) {
	k.keyPress(key)
	time.Sleep(100 * time.Millisecond) //ignore if speed is most in my test system
	k.keyRelease(key)
}

const (
	VK_SP1  = 0x0A
	VK_SP2  = 0x1B
	VK_SP3  = 0x18
	VK_SP4  = 0x21
	VK_SP5  = 0x1E
	VK_SP6  = 0x29
	VK_SP7  = 0x27
	VK_SP8  = 0x2A
	VK_SP9  = 0x2B
	VK_SP10 = 0x2F
	VK_SP11 = 0x2C
	VK_SP12 = 0x32

	VK_A              = 0x00
	VK_S              = 0x01
	VK_D              = 0x02
	VK_F              = 0x03
	VK_H              = 0x04
	VK_G              = 0x05
	VK_Z              = 0x06
	VK_X              = 0x07
	VK_C              = 0x08
	VK_V              = 0x09
	VK_B              = 0x0B
	VK_Q              = 0x0C
	VK_W              = 0x0D
	VK_E              = 0x0E
	VK_R              = 0x0F
	VK_Y              = 0x10
	VK_T              = 0x11
	VK_1              = 0x12
	VK_2              = 0x13
	VK_3              = 0x14
	VK_4              = 0x15
	VK_6              = 0x16
	VK_5              = 0x17
	VK_EQUAL          = 0x18
	VK_9              = 0x19
	VK_7              = 0x1A
	VK_MINUS          = 0x1B
	VK_8              = 0x1C
	VK_0              = 0x1D
	VK_RightBracket   = 0x1E
	VK_O              = 0x1F
	VK_U              = 0x20
	VK_LeftBracket    = 0x21
	VK_I              = 0x22
	VK_P              = 0x23
	VK_L              = 0x25
	VK_J              = 0x26
	VK_Quote          = 0x27
	VK_K              = 0x28
	VK_SEMICOLON      = 0x29
	VK_BACKSLASH      = 0x2A
	VK_COMMA          = 0x2B
	VK_SLASH          = 0x2C
	VK_N              = 0x2D
	VK_M              = 0x2E
	VK_Period         = 0x2F
	VK_GRAVE          = 0x32
	VK_KeypadDecimal  = 0x41
	VK_KeypadMultiply = 0x43
	VK_KeypadPlus     = 0x45
	VK_KeypadClear    = 0x47
	VK_KeypadDivide   = 0x4B
	VK_KeypadEnter    = 0x4C
	VK_KeypadMinus    = 0x4E
	VK_KeypadEquals   = 0x51
	VK_Keypad0        = 0x52
	VK_Keypad1        = 0x53
	VK_Keypad2        = 0x54
	VK_Keypad3        = 0x55
	VK_Keypad4        = 0x56
	VK_Keypad5        = 0x57
	VK_Keypad6        = 0x58
	VK_Keypad7        = 0x59
	VK_Keypad8        = 0x5B
	VK_Keypad9        = 0x5C

	VK_ENTER         = 0x24
	VK_TAB           = 0x30
	VK_SPACE         = 0x31
	VK_DELETE        = 0x33
	VK_ESC           = 0x35
	VK_CAPSLOCK      = 0x39
	VK_Option        = 0x3A
	VK_RightOption   = 0x3D
	VK_Function      = 0x3F
	VK_F17           = 0x40
	VK_VOLUMEUP      = 0x48
	VK_VOLUMEDOWN    = 0x49
	VK_MUTE          = 0x4A
	VK_F18           = 0x4F
	VK_F19           = 0x50
	VK_F20           = 0x5A
	VK_F5            = 0x60
	VK_F6            = 0x61
	VK_F7            = 0x62
	VK_F3            = 0x63
	VK_F8            = 0x64
	VK_F9            = 0x65
	VK_F11           = 0x67
	VK_F13           = 0x69
	VK_F16           = 0x6A
	VK_F14           = 0x6B
	VK_F10           = 0x6D
	VK_F12           = 0x6F
	VK_F15           = 0x71
	VK_HELP          = 0x72
	VK_HOME          = 0x73
	VK_PAGEUP        = 0x74
	VK_ForwardDelete = 0x75
	VK_F4            = 0x76
	VK_END           = 0x77
	VK_F2            = 0x78
	VK_PAGEDOWN      = 0x79
	VK_F1            = 0x7A
	VK_LEFT          = 0x7B
	VK_RIGHT         = 0x7C
	VK_DOWN          = 0x7D
	VK_UP            = 0x7E
)
<commit_msg>fix: imported missing ApplicationServices.h file<commit_after>package keybd_event

/*
 #cgo CFLAGS: -x objective-c
 #cgo LDFLAGS: -framework Cocoa
 #import <Foundation/Foundation.h>
 #import <ApplicationServices/ApplicationServices.h>
 CGEventRef CreateDown(int k){
	CGEventRef event = CGEventCreateKeyboardEvent (NULL, (CGKeyCode)k, true);
	return event;
 }
 CGEventRef CreateUp(int k){
	CGEventRef event = CGEventCreateKeyboardEvent (NULL, (CGKeyCode)k, false);
	return event;
 }
 void KeyTap(CGEventRef event){
	CGEventPost(kCGAnnotatedSessionEventTap, event);
	CFRelease(event);
 }
 void AddActionKey(CGEventFlags type,CGEventRef event){
 	CGEventSetFlags(event, type);
 }
*/
import "C"
import "time"

const (
	_AShift          = C.kCGEventFlagMaskAlphaShift
	_VK_SHIFT        = C.kCGEventFlagMaskShift
	_VK_CTRL         = C.kCGEventFlagMaskControl
	_VK_ALT          = C.kCGEventFlagMaskAlternate
	_VK_CMD          = C.kCGEventFlagMaskCommand
	_Help            = C.kCGEventFlagMaskHelp
	_VK_FN           = C.kCGEventFlagMaskSecondaryFn
	_NumPad          = C.kCGEventFlagMaskNumericPad
	_Coalesced       = C.kCGEventFlagMaskNonCoalesced
	_VK_Control      = 0x3B
	_VK_RightShift   = 0x3C
	_VK_RightControl = 0x3E
	_VK_Command      = 0x37
	_VK_Shift        = 0x38
)

func initKeyBD() error { return nil }

// Press key(s)
func (k *KeyBonding) Press() error {
	for _, key := range k.keys {
		k.keyPress(key)
	}
	return nil
}

// Release key(s)
func (k *KeyBonding) Release() error {
	for _, key := range k.keys {
		k.keyRelease(key)
	}
	return nil
}

// Launch key bounding
func (k *KeyBonding) Launching() error {

	for _, key := range k.keys {
		k.tapKey(key)
	}
	return nil
}
func altgr(event C.CGEventRef) {
	alt(event)
}
func shift(event C.CGEventRef) {
	C.AddActionKey(_VK_SHIFT, event)
}
func ctrl(event C.CGEventRef) {
	C.AddActionKey(_VK_CTRL, event)
}
func alt(event C.CGEventRef) {
	C.AddActionKey(_VK_ALT, event)
}
func cmd(event C.CGEventRef) {
	C.AddActionKey(_VK_CMD, event)
}
func (k KeyBonding) keyPress(key int) {
	downEvent := C.CreateDown(C.int(key))
	if k.hasALT {
		alt(downEvent)
	}
	if k.hasCTRL {
		ctrl(downEvent)
	}
	if k.hasSHIFT {
		shift(downEvent)
	}
	if k.hasRCTRL { //not support on mac
		ctrl(downEvent)
	}
	if k.hasRSHIFT { //not support on mac
		shift(downEvent)
	}
	if k.hasALTGR {
		altgr(downEvent)
	}
	if k.hasSuper {
		cmd(downEvent)
	}
	C.KeyTap(downEvent)
}
func (k KeyBonding) keyRelease(key int) {
	upEvent := C.CreateUp(C.int(key))
	if k.hasALT {
		alt(upEvent)
	}
	if k.hasCTRL {
		ctrl(upEvent)
	}
	if k.hasSHIFT {
		shift(upEvent)
	}
	if k.hasRCTRL { //not support on mac
		ctrl(upEvent)
	}
	if k.hasRSHIFT { //not support on mac
		shift(upEvent)
	}
	if k.hasALTGR {
		altgr(upEvent)
	}
	if k.hasSuper {
		cmd(upEvent)
	}
	C.KeyTap(upEvent)
}
func (k KeyBonding) tapKey(key int) {
	k.keyPress(key)
	time.Sleep(100 * time.Millisecond) //ignore if speed is most in my test system
	k.keyRelease(key)
}

const (
	VK_SP1  = 0x0A
	VK_SP2  = 0x1B
	VK_SP3  = 0x18
	VK_SP4  = 0x21
	VK_SP5  = 0x1E
	VK_SP6  = 0x29
	VK_SP7  = 0x27
	VK_SP8  = 0x2A
	VK_SP9  = 0x2B
	VK_SP10 = 0x2F
	VK_SP11 = 0x2C
	VK_SP12 = 0x32

	VK_A              = 0x00
	VK_S              = 0x01
	VK_D              = 0x02
	VK_F              = 0x03
	VK_H              = 0x04
	VK_G              = 0x05
	VK_Z              = 0x06
	VK_X              = 0x07
	VK_C              = 0x08
	VK_V              = 0x09
	VK_B              = 0x0B
	VK_Q              = 0x0C
	VK_W              = 0x0D
	VK_E              = 0x0E
	VK_R              = 0x0F
	VK_Y              = 0x10
	VK_T              = 0x11
	VK_1              = 0x12
	VK_2              = 0x13
	VK_3              = 0x14
	VK_4              = 0x15
	VK_6              = 0x16
	VK_5              = 0x17
	VK_EQUAL          = 0x18
	VK_9              = 0x19
	VK_7              = 0x1A
	VK_MINUS          = 0x1B
	VK_8              = 0x1C
	VK_0              = 0x1D
	VK_RightBracket   = 0x1E
	VK_O              = 0x1F
	VK_U              = 0x20
	VK_LeftBracket    = 0x21
	VK_I              = 0x22
	VK_P              = 0x23
	VK_L              = 0x25
	VK_J              = 0x26
	VK_Quote          = 0x27
	VK_K              = 0x28
	VK_SEMICOLON      = 0x29
	VK_BACKSLASH      = 0x2A
	VK_COMMA          = 0x2B
	VK_SLASH          = 0x2C
	VK_N              = 0x2D
	VK_M              = 0x2E
	VK_Period         = 0x2F
	VK_GRAVE          = 0x32
	VK_KeypadDecimal  = 0x41
	VK_KeypadMultiply = 0x43
	VK_KeypadPlus     = 0x45
	VK_KeypadClear    = 0x47
	VK_KeypadDivide   = 0x4B
	VK_KeypadEnter    = 0x4C
	VK_KeypadMinus    = 0x4E
	VK_KeypadEquals   = 0x51
	VK_Keypad0        = 0x52
	VK_Keypad1        = 0x53
	VK_Keypad2        = 0x54
	VK_Keypad3        = 0x55
	VK_Keypad4        = 0x56
	VK_Keypad5        = 0x57
	VK_Keypad6        = 0x58
	VK_Keypad7        = 0x59
	VK_Keypad8        = 0x5B
	VK_Keypad9        = 0x5C

	VK_ENTER         = 0x24
	VK_TAB           = 0x30
	VK_SPACE         = 0x31
	VK_DELETE        = 0x33
	VK_ESC           = 0x35
	VK_CAPSLOCK      = 0x39
	VK_Option        = 0x3A
	VK_RightOption   = 0x3D
	VK_Function      = 0x3F
	VK_F17           = 0x40
	VK_VOLUMEUP      = 0x48
	VK_VOLUMEDOWN    = 0x49
	VK_MUTE          = 0x4A
	VK_F18           = 0x4F
	VK_F19           = 0x50
	VK_F20           = 0x5A
	VK_F5            = 0x60
	VK_F6            = 0x61
	VK_F7            = 0x62
	VK_F3            = 0x63
	VK_F8            = 0x64
	VK_F9            = 0x65
	VK_F11           = 0x67
	VK_F13           = 0x69
	VK_F16           = 0x6A
	VK_F14           = 0x6B
	VK_F10           = 0x6D
	VK_F12           = 0x6F
	VK_F15           = 0x71
	VK_HELP          = 0x72
	VK_HOME          = 0x73
	VK_PAGEUP        = 0x74
	VK_ForwardDelete = 0x75
	VK_F4            = 0x76
	VK_END           = 0x77
	VK_F2            = 0x78
	VK_PAGEDOWN      = 0x79
	VK_F1            = 0x7A
	VK_LEFT          = 0x7B
	VK_RIGHT         = 0x7C
	VK_DOWN          = 0x7D
	VK_UP            = 0x7E
)
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"io/ioutil"
	"os"

	"github.com/pivotal-cf/email-resource/out"
)

var (
	//VERSION -
	VERSION string
)

func main() {
	sourceRoot := os.Args[1]
	inbytes, err := ioutil.ReadAll(os.Stdin)
	if err != nil {
		fmt.Fprintln(os.Stderr, err.Error())
		os.Exit(1)
	}
	output, err := out.Execute(sourceRoot, VERSION, inbytes)
	if err != nil {
		fmt.Fprintln(os.Stderr, err.Error())
		os.Exit(1)
	}
	fmt.Println(output)
}
<commit_msg>ensure output is added to sysout<commit_after>package main

import (
	"fmt"
	"io/ioutil"
	"os"

	"github.com/pivotal-cf/email-resource/out"
)

var (
	//VERSION -
	VERSION string
)

func main() {
	sourceRoot := os.Args[1]
	inbytes, err := ioutil.ReadAll(os.Stdin)
	if err != nil {
		fmt.Fprintln(os.Stderr, err.Error())
		os.Exit(1)
	}
	output, err := out.Execute(sourceRoot, VERSION, inbytes)
	if err != nil {
		fmt.Fprintln(os.Stderr, err.Error())
		fmt.Println(output)
		os.Exit(1)
	}
	fmt.Println(output)
}
<|endoftext|>


<commit_before>// Copyright 2012 The Gorilla Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package mongodb

import (
	"bytes"
	"net/http"
	"testing"

	"code.google.com/p/gorilla/sessions"
	"launchpad.net/mgo"
)

// ----------------------------------------------------------------------------
// ResponseRecorder
// ----------------------------------------------------------------------------
// Copyright 2009 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

// ResponseRecorder is an implementation of http.ResponseWriter that
// records its mutations for later inspection in tests.
type ResponseRecorder struct {
	Code      int           // the HTTP response code from WriteHeader
	HeaderMap http.Header   // the HTTP response headers
	Body      *bytes.Buffer // if non-nil, the bytes.Buffer to append written data to
	Flushed   bool
}

// NewRecorder returns an initialized ResponseRecorder.
func NewRecorder() *ResponseRecorder {
	return &ResponseRecorder{
		HeaderMap: make(http.Header),
		Body:      new(bytes.Buffer),
	}
}

// DefaultRemoteAddr is the default remote address to return in RemoteAddr if
// an explicit DefaultRemoteAddr isn't set on ResponseRecorder.
const DefaultRemoteAddr = "1.2.3.4"

// Header returns the response headers.
func (rw *ResponseRecorder) Header() http.Header {
	return rw.HeaderMap
}

// Write always succeeds and writes to rw.Body, if not nil.
func (rw *ResponseRecorder) Write(buf []byte) (int, error) {
	if rw.Body != nil {
		rw.Body.Write(buf)
	}
	if rw.Code == 0 {
		rw.Code = http.StatusOK
	}
	return len(buf), nil
}

// WriteHeader sets rw.Code.
func (rw *ResponseRecorder) WriteHeader(code int) {
	rw.Code = code
}

// Flush sets rw.Flushed to true.
func (rw *ResponseRecorder) Flush() {
	rw.Flushed = true
}

// ----------------------------------------------------------------------------

func getRequest() *http.Request {
	r, _ := http.NewRequest("GET", "http://localhost", nil)
	r.Header.Set("App-Testing", "1")
	return r
}

// ----------------------------------------------------------------------------

func TestMongoFlashes(t *testing.T) {
	session, err := mgo.Dial("mongodb://127.0.0.1:27017")
	if err != nil {
		t.Fatal(err)
	}
	db := &mgo.Database{
		Session: session,
		Name:    "mydb",
	}
	collection := &mgo.Collection{
		Database: db,
		Name:     "collection",
		FullName: "db.collection",
	}
	store := NewMongoStore(collection, []byte("secret-key"))
	testSessionFlashes(t, store)
}

// ----------------------------------------------------------------------------

func testSessionFlashes(t *testing.T, store sessions.Store) {
	var req *http.Request
	var rsp *ResponseRecorder
	var hdr http.Header
	var err error
	var ok bool
	var cookies []string
	var session *sessions.Session
	var flashes []interface{}

	// Round 1 ----------------------------------------------------------------

	req = getRequest()
	rsp = NewRecorder()
	// Get a session.
	if session, err = store.Get(req, "session-key"); err != nil {
		t.Fatalf("Error getting session: %v", err)
	}
	// Get a flash.
	flashes = session.Flashes()
	if len(flashes) != 0 {
		t.Errorf("Expected empty flashes; Got %v", flashes)
	}
	// Add some flashes.
	session.AddFlash("foo")
	session.AddFlash("bar")
	// Custom key.
	session.AddFlash("baz", "custom_key")
	// Save.
	if err = sessions.Save(req, rsp); err != nil {
		t.Fatalf("Error saving session: %v", err)
	}
	hdr = rsp.Header()
	cookies, ok = hdr["Set-Cookie"]
	if !ok || len(cookies) != 1 {
		t.Fatalf("No cookies. Header:", hdr)
	}

	// Round 2 ----------------------------------------------------------------

	req = getRequest()
	req.Header.Add("Cookie", cookies[0])
	rsp = NewRecorder()
	// Get a session.
	if session, err = store.Get(req, "session-key"); err != nil {
		t.Fatalf("Error getting session: %v", err)
	}
	// Check all saved values.
	flashes = session.Flashes()
	if len(flashes) != 2 {
		t.Fatalf("Expected flashes; Got %v", flashes)
	}
	if flashes[0] != "foo" || flashes[1] != "bar" {
		t.Errorf("Expected foo,bar; Got %v", flashes)
	}
	flashes = session.Flashes()
	if len(flashes) != 0 {
		t.Errorf("Expected dumped flashes; Got %v", flashes)
	}
	// Custom key.
	flashes = session.Flashes("custom_key")
	if len(flashes) != 1 {
		t.Errorf("Expected flashes; Got %v", flashes)
	} else if flashes[0] != "baz" {
		t.Errorf("Expected baz; Got %v", flashes)
	}
	flashes = session.Flashes("custom_key")
	if len(flashes) != 0 {
		t.Errorf("Expected dumped flashes; Got %v", flashes)
	}
}
<commit_msg>shorter mgo test code.<commit_after>// Copyright 2012 The Gorilla Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package mongodb

import (
	"bytes"
	"net/http"
	"testing"

	"code.google.com/p/gorilla/sessions"
	"launchpad.net/mgo"
)

// ----------------------------------------------------------------------------
// ResponseRecorder
// ----------------------------------------------------------------------------
// Copyright 2009 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

// ResponseRecorder is an implementation of http.ResponseWriter that
// records its mutations for later inspection in tests.
type ResponseRecorder struct {
	Code      int           // the HTTP response code from WriteHeader
	HeaderMap http.Header   // the HTTP response headers
	Body      *bytes.Buffer // if non-nil, the bytes.Buffer to append written data to
	Flushed   bool
}

// NewRecorder returns an initialized ResponseRecorder.
func NewRecorder() *ResponseRecorder {
	return &ResponseRecorder{
		HeaderMap: make(http.Header),
		Body:      new(bytes.Buffer),
	}
}

// DefaultRemoteAddr is the default remote address to return in RemoteAddr if
// an explicit DefaultRemoteAddr isn't set on ResponseRecorder.
const DefaultRemoteAddr = "1.2.3.4"

// Header returns the response headers.
func (rw *ResponseRecorder) Header() http.Header {
	return rw.HeaderMap
}

// Write always succeeds and writes to rw.Body, if not nil.
func (rw *ResponseRecorder) Write(buf []byte) (int, error) {
	if rw.Body != nil {
		rw.Body.Write(buf)
	}
	if rw.Code == 0 {
		rw.Code = http.StatusOK
	}
	return len(buf), nil
}

// WriteHeader sets rw.Code.
func (rw *ResponseRecorder) WriteHeader(code int) {
	rw.Code = code
}

// Flush sets rw.Flushed to true.
func (rw *ResponseRecorder) Flush() {
	rw.Flushed = true
}

// ----------------------------------------------------------------------------

func getRequest() *http.Request {
	r, _ := http.NewRequest("GET", "http://localhost", nil)
	r.Header.Set("App-Testing", "1")
	return r
}

// ----------------------------------------------------------------------------

func TestMongoFlashes(t *testing.T) {
	s, err := mgo.Dial("localhost")
	if err != nil {
		t.Fatal(err)
	}
	store := NewMongoStore(s.DB("db").C("collection"), []byte("secret-key"))
	testSessionFlashes(t, store)
}

// ----------------------------------------------------------------------------

func testSessionFlashes(t *testing.T, store sessions.Store) {
	var req *http.Request
	var rsp *ResponseRecorder
	var hdr http.Header
	var err error
	var ok bool
	var cookies []string
	var session *sessions.Session
	var flashes []interface{}

	// Round 1 ----------------------------------------------------------------

	req = getRequest()
	rsp = NewRecorder()
	// Get a session.
	if session, err = store.Get(req, "session-key"); err != nil {
		t.Fatalf("Error getting session: %v", err)
	}
	// Get a flash.
	flashes = session.Flashes()
	if len(flashes) != 0 {
		t.Errorf("Expected empty flashes; Got %v", flashes)
	}
	// Add some flashes.
	session.AddFlash("foo")
	session.AddFlash("bar")
	// Custom key.
	session.AddFlash("baz", "custom_key")
	// Save.
	if err = sessions.Save(req, rsp); err != nil {
		t.Fatalf("Error saving session: %v", err)
	}
	hdr = rsp.Header()
	cookies, ok = hdr["Set-Cookie"]
	if !ok || len(cookies) != 1 {
		t.Fatalf("No cookies. Header:", hdr)
	}

	// Round 2 ----------------------------------------------------------------

	req = getRequest()
	req.Header.Add("Cookie", cookies[0])
	rsp = NewRecorder()
	// Get a session.
	if session, err = store.Get(req, "session-key"); err != nil {
		t.Fatalf("Error getting session: %v", err)
	}
	// Check all saved values.
	flashes = session.Flashes()
	if len(flashes) != 2 {
		t.Fatalf("Expected flashes; Got %v", flashes)
	}
	if flashes[0] != "foo" || flashes[1] != "bar" {
		t.Errorf("Expected foo,bar; Got %v", flashes)
	}
	flashes = session.Flashes()
	if len(flashes) != 0 {
		t.Errorf("Expected dumped flashes; Got %v", flashes)
	}
	// Custom key.
	flashes = session.Flashes("custom_key")
	if len(flashes) != 1 {
		t.Errorf("Expected flashes; Got %v", flashes)
	} else if flashes[0] != "baz" {
		t.Errorf("Expected baz; Got %v", flashes)
	}
	flashes = session.Flashes("custom_key")
	if len(flashes) != 0 {
		t.Errorf("Expected dumped flashes; Got %v", flashes)
	}
}
<|endoftext|>


<commit_before>package logger

import(
    // "io/ioutil"
    "os"
    "bufio"
    "fmt"
    "time"
)

type slog struct {
    ty string
    path string
    size int64
    date string
    w *bufio.Writer
}

func (l *slog) New() *slog{
    f := l.newFile()
    l.date = time.Now().Format("2006-01-02")

    w := bufio.NewWriter(f)
    l.w = w
    w.Write([]byte("test"))
    w.Flush()

    return l
}

func (l *slog) newFile() *os.File{
    f, err := os.OpenFile(l.path, os.O_CREATE|os.O_APPEND|os.O_RDWR, 0666)
    if err != nil {
        fmt.Println(err)
    }
    defer f.Close()
    return f
}

// 普通信息
func (l *slog) Info(info string) {
    now := time.Now().Format("2006-01-02 15:04:05.000")
    l.w.WriteString(now + " " + info)
}

// 错误信息
func (l *slog) Error(errorInfo string) {
    now := time.Now().Format("2006-01-02 15:04:05.000")
    l.w.WriteString(now + " " + errorInfo)
}

// 文件大小&日期检测
func (l *slog) check() {
    now := time.Now().Format("2006-01-02")
    if now != l.date {

    }

}
<commit_msg>update log module<commit_after>package logger

import(
    // "io/ioutil"
    "os"
    "bufio"
    "fmt"
    "time"
)

var (
    formatStr = "2006-01-02 15:04:05.000"
    shortFormat = "2006-01-02"
)

type slog struct {
    ty string
    path string
    size int64
    date string
    w *bufio.Writer
}

func (l *slog) New() *slog{
    f := l.newFile()
    l.date = time.Now().Format(shortFormat)

    w := bufio.NewWriter(f)
    l.w = w
    w.Write([]byte("test"))
    w.Flush()

    return l
}

func (l *slog) newFile() *os.File{
    f, err := os.OpenFile(l.path, os.O_CREATE|os.O_APPEND|os.O_RDWR, 0666)
    if err != nil {
        fmt.Println(err)
    }
    defer f.Close()
    return f
}

// 普通信息
func (l *slog) Info(info string) {
    now := time.Now().Format(formatStr)
    l.w.WriteString(now + " " + info)
}

// 错误信息
func (l *slog) Error(errorInfo string) {
    now := time.Now().Format(formatStr)
    l.w.WriteString(now + " " + errorInfo)
}

// 文件大小&日期检测
func (l *slog) check() {
    now := time.Now().Format(shortFormat)
    if now != l.date {

    }

}
<|endoftext|>


<commit_before>package logger

import(
    "os"
    "bufio"
    "fmt"
    "time"
    "path/filepath"
)

var (
    crtAccessIndex = 0
    crtErrorIndex = 0
)

const (
    infoLog = "access.log."
    errorLog = "error.log."
    formatStr = "2006-01-02 15:04:05.000"
    shortFormat = "2006-01-02"
    maxfileSize int64 = 1024 * 1024 * 10
)

type slog struct {
    ty string
    path string
    size int64
    date string
    accessWr *bufio.Writer
    errorWr *bufio.Writer
    crtAccessLogPath string
    crtErrorLogPath string
}

// 日志模块初始化
func (l *slog) New(logPath string) *slog{
    dirPath := filepath.Dir(logPath)
    l.path = dirPath
    l.date = time.Now().Format(shortFormat)
    l.newFile("all", l.date)

    l.accessWr.Write([]byte("test"))
    l.accessWr.Flush()
    return l
}

// 日志文件管理
func (l *slog) newFile(ty string, date string){
    accessLogPath := l.path + infoLog + date
    errorLogPath := l.path + infoLog + date
    l.crtAccessLogPath = accessLogPath
    l.crtErrorLogPath = errorLogPath

    if ty == "all" {
        l.newSimpleFile(l.crtAccessLogPath, "access")
        l.newSimpleFile(l.crtErrorLogPath, "error")
    } else if ty == "access" {
        l.newSimpleFile(l.crtAccessLogPath, "access")
    } else if ty == "error" {
        l.newSimpleFile(l.crtErrorLogPath, "error")
    }
}

// 处理单个日志文件
func (l *slog) newSimpleFile(p , ty string){
    f, err := os.OpenFile(p , os.O_CREATE | os.O_APPEND | os.O_RDWR, 0666)
    if err != nil {
        fmt.Println(err)
    }
    defer f.Close()
    w := bufio.NewWriter(f)

    if ty == "access" {
        l.accessWr = w
    } else if ty == "error" {
        l.errorWr = w
    }
}

// 普通信息
func (l *slog) Info(info string) {
    now := time.Now().Format(formatStr)
    l.accessWr.WriteString(now + " " + info)
}

// 错误信息
func (l *slog) Error(errorInfo string) {
    now := time.Now().Format(formatStr)
    l.accessWr.WriteString(now + " " + errorInfo)
}

// 文件大小&日期检测
func (l *slog) check() {
    now := time.Now().Format(shortFormat)
    if now != l.date {
        l.newFile("all", l.date)
        crtAccessIndex = 0
        crtErrorIndex = 0
    }

    l.overSize("access")
    l.overSize("error")
}

func  (l *slog) overSize(ty string) {
    path := ""

    if ty == "access" {
        crtAccessIndex ++
        path = l.crtAccessLogPath + string(crtAccessIndex)
    } else if ty == "error" {
        crtErrorIndex ++
        path = l.crtErrorLogPath + string(crtErrorIndex)
    }

    fileSize, err := fileSize(path)
    if err != nil {
        fmt.Println(err)
    }

    if fileSize > maxfileSize {
        l.newSimpleFile(path, ty)
    }
}

// 检测文件大小
func fileSize(file string) (int64, error) {
	f, e := os.Stat(file)
	if e != nil {
		return 0, e
	}
	return f.Size(), nil
}
<commit_msg>update log module<commit_after>package logger

import(
    "os"
    "bufio"
    "fmt"
    "time"
    "path/filepath"
    "strconv"
)

var (
    crtAccessIndex = 0
    crtErrorIndex = 0
)

const (
    infoLog = "access.log."
    errorLog = "error.log."
    formatStr = "2006-01-02 15:04:05.000"
    shortFormat = "2006-01-02"
    maxfileSize int64 = 1024 * 1024 * 10
)

type slog struct {
    ty string
    path string
    size int64
    date string
    accessWr *bufio.Writer
    errorWr *bufio.Writer
    crtAccessLogPath string
    crtErrorLogPath string
}

// 日志模块初始化
func (l *slog) New(logPath string) *slog{
    dirPath := filepath.Dir(logPath)
    l.path = dirPath
    l.date = time.Now().Format(shortFormat)
    l.newFile("all", l.date)

    l.accessWr.Write([]byte("test"))
    l.accessWr.Flush()
    return l
}

// 日志文件管理
func (l *slog) newFile(ty string, date string){
    accessLogPath := l.path + infoLog + date
    errorLogPath := l.path + infoLog + date
    l.crtAccessLogPath = accessLogPath
    l.crtErrorLogPath = errorLogPath

    if ty == "all" {
        l.newSimpleFile(l.crtAccessLogPath, "access")
        l.newSimpleFile(l.crtErrorLogPath, "error")
    } else if ty == "access" {
        l.newSimpleFile(l.crtAccessLogPath, "access")
    } else if ty == "error" {
        l.newSimpleFile(l.crtErrorLogPath, "error")
    }
}

// 处理单个日志文件
func (l *slog) newSimpleFile(p , ty string){
    f, err := os.OpenFile(p , os.O_CREATE | os.O_APPEND | os.O_RDWR, 0666)
    if err != nil {
        fmt.Println(err)
    }
    defer f.Close()
    w := bufio.NewWriter(f)

    if ty == "access" {
        l.accessWr = w
    } else if ty == "error" {
        l.errorWr = w
    }
}

// 普通信息
func (l *slog) Info(info string) {
    now := time.Now().Format(formatStr)
    l.accessWr.WriteString(now + " " + info)
}

// 错误信息
func (l *slog) Error(errorInfo string) {
    now := time.Now().Format(formatStr)
    l.accessWr.WriteString(now + " " + errorInfo)
}

// 文件大小&日期检测
func (l *slog) check() {
    now := time.Now().Format(shortFormat)
    if now != l.date {
        l.newFile("all", l.date)
        crtAccessIndex = 0
        crtErrorIndex = 0
    }

    l.overSize("access")
    l.overSize("error")
}

func  (l *slog) overSize(ty string) {
    path := ""

    if ty == "access" {
        crtAccessIndex ++
        path = l.crtAccessLogPath + strconv.Itoa(crtAccessIndex)
    } else if ty == "error" {
        crtErrorIndex ++
        path = l.crtErrorLogPath + strconv.Itoa(crtErrorIndex)
    }

    fileSize, err := fileSize(path)
    if err != nil {
        fmt.Println(err)
    }

    if fileSize > maxfileSize {
        l.newSimpleFile(path, ty)
    }
}

// 检测文件大小
func fileSize(file string) (int64, error) {
	f, e := os.Stat(file)
	if e != nil {
		return 0, e
	}
	return f.Size(), nil
}
<|endoftext|>